From 66d43b882e75dbeba5f250c17f9240aceb536cee Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 4 Aug 2021 11:58:50 +0200 Subject: [PATCH 01/60] Fixed calls set_uniform(emission_factor, xx) to use floats --- src/slic3r/GUI/3DBed.cpp | 4 ++-- src/slic3r/GUI/GCodeViewer.cpp | 2 +- src/slic3r/GUI/GLCanvas3D.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoCut.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoMove.cpp | 4 ++-- src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoScale.cpp | 8 ++++---- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 4 ++-- src/slic3r/GUI/Selection.cpp | 2 +- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index d7fb937d0..7b08b5f79 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -119,7 +119,7 @@ void Bed3D::Axes::render() const glsafe(::glEnable(GL_DEPTH_TEST)); shader->start_using(); - shader->set_uniform("emission_factor", 0.0); + shader->set_uniform("emission_factor", 0.0f); // x axis const_cast(&m_arrow)->set_color(-1, { 0.75f, 0.0f, 0.0f, 1.0f }); @@ -498,7 +498,7 @@ void Bed3D::render_model() const GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader != nullptr) { shader->start_using(); - shader->set_uniform("emission_factor", 0.0); + shader->set_uniform("emission_factor", 0.0f); glsafe(::glPushMatrix()); glsafe(::glTranslated(m_model_offset.x(), m_model_offset.y(), m_model_offset.z())); model->render(); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 090accb6a..b9a7d2338 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -223,7 +223,7 @@ void GCodeViewer::SequentialView::Marker::render() const glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); shader->start_using(); - shader->set_uniform("emission_factor", 0.0); + shader->set_uniform("emission_factor", 0.0f); glsafe(::glPushMatrix()); glsafe(::glMultMatrixf(m_world_transform.data())); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f366100ac..e2699fb6d 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4148,7 +4148,7 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const glsafe(::glEnable(GL_DEPTH_TEST)); shader->start_using(); - shader->set_uniform("emission_factor", 0.0); + shader->set_uniform("emission_factor", 0.0f); for (GLVolume* vol : visible_volumes) { shader->set_uniform("uniform_color", (vol->printable && !vol->is_outside) ? orange : gray); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 92c03cb75..1177c46ca 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -183,7 +183,7 @@ void GLGizmoBase::render_grabbers(float size) const if (shader == nullptr) return; shader->start_using(); - shader->set_uniform("emission_factor", 0.1); + shader->set_uniform("emission_factor", 0.1f); for (int i = 0; i < (int)m_grabbers.size(); ++i) { if (m_grabbers[i].enabled) m_grabbers[i].render(m_hover_id == i, size); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp index 707726e08..27b54c595 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoCut.cpp @@ -136,7 +136,7 @@ void GLGizmoCut::on_render() if (shader == nullptr) return; shader->start_using(); - shader->set_uniform("emission_factor", 0.1); + shader->set_uniform("emission_factor", 0.1f); m_grabbers[0].color = GrabberColor; m_grabbers[0].render(m_hover_id == 0, (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0)); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp index 1211864eb..9a056adcb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMove.cpp @@ -141,7 +141,7 @@ void GLGizmoMove3D::on_render() GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader != nullptr) { shader->start_using(); - shader->set_uniform("emission_factor", 0.1); + shader->set_uniform("emission_factor", 0.1f); // draw grabber float mean_size = (float)((box.size().x() + box.size().y() + box.size().z()) / 3.0); m_grabbers[m_hover_id].render(true, mean_size); @@ -208,7 +208,7 @@ void GLGizmoMove3D::render_grabber_extension(Axis axis, const BoundingBoxf3& box const_cast(&m_vbo_cone)->set_color(-1, color); if (!picking) { shader->start_using(); - shader->set_uniform("emission_factor", 0.1); + shader->set_uniform("emission_factor", 0.1f); } glsafe(::glPushMatrix()); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp index a495db4f1..2e32a2568 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoRotate.cpp @@ -339,7 +339,7 @@ void GLGizmoRotate::render_grabber_extension(const BoundingBoxf3& box, bool pick const_cast(&m_cone)->set_color(-1, color); if (!picking) { shader->start_using(); - shader->set_uniform("emission_factor", 0.1); + shader->set_uniform("emission_factor", 0.1f); } glsafe(::glPushMatrix()); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp index 849046962..894d844d8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoScale.cpp @@ -236,7 +236,7 @@ void GLGizmoScale3D::on_render() GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader != nullptr) { shader->start_using(); - shader->set_uniform("emission_factor", 0.1); + shader->set_uniform("emission_factor", 0.1f); // draw grabbers m_grabbers[0].render(true, grabber_mean_size); m_grabbers[1].render(true, grabber_mean_size); @@ -251,7 +251,7 @@ void GLGizmoScale3D::on_render() GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader != nullptr) { shader->start_using(); - shader->set_uniform("emission_factor", 0.1); + shader->set_uniform("emission_factor", 0.1f); // draw grabbers m_grabbers[2].render(true, grabber_mean_size); m_grabbers[3].render(true, grabber_mean_size); @@ -266,7 +266,7 @@ void GLGizmoScale3D::on_render() GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader != nullptr) { shader->start_using(); - shader->set_uniform("emission_factor", 0.1); + shader->set_uniform("emission_factor", 0.1f); // draw grabbers m_grabbers[4].render(true, grabber_mean_size); m_grabbers[5].render(true, grabber_mean_size); @@ -284,7 +284,7 @@ void GLGizmoScale3D::on_render() GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); if (shader != nullptr) { shader->start_using(); - shader->set_uniform("emission_factor", 0.1); + shader->set_uniform("emission_factor", 0.1f); // draw grabbers for (int i = 6; i < 10; ++i) { m_grabbers[i].render(true, grabber_mean_size); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index fa61779ec..71607b351 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -169,7 +169,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) const_cast(&m_cone)->set_color(-1, render_color); const_cast(&m_sphere)->set_color(-1, render_color); if (shader && !picking) - shader->set_uniform("emission_factor", 0.5); + shader->set_uniform("emission_factor", 0.5f); // Inverse matrix of the instance scaling is applied so that the mark does not scale with the object. glsafe(::glPushMatrix()); @@ -224,7 +224,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) render_color[3] = 0.7f; const_cast(&m_cylinder)->set_color(-1, render_color); if (shader) - shader->set_uniform("emission_factor", 0.5); + shader->set_uniform("emission_factor", 0.5f); for (const sla::DrainHole& drain_hole : m_c->selection_info()->model_object()->sla_drain_holes) { if (is_mesh_point_clipped(drain_hole.pos.cast())) continue; diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index dbc259444..6a47113fa 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -1872,7 +1872,7 @@ void Selection::render_sidebar_scale_hints(const std::string& sidebar_field) con const_cast(&m_arrow)->set_color(-1, uniform_scale ? UNIFORM_SCALE_COLOR : get_color(axis)); GLShaderProgram* shader = wxGetApp().get_current_shader(); if (shader != nullptr) - shader->set_uniform("emission_factor", 0.0); + shader->set_uniform("emission_factor", 0.0f); glsafe(::glTranslated(0.0, 5.0, 0.0)); m_arrow.render(); From 599a4d97e38b0c7b50eeb4433b9f1ba007444d97 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 4 Aug 2021 12:47:36 +0200 Subject: [PATCH 02/60] Removed constness from a few renderXXX() methods --- src/slic3r/GUI/GCodeViewer.cpp | 40 ++++++++++++++++------------------ src/slic3r/GUI/GCodeViewer.hpp | 10 ++++----- src/slic3r/GUI/GLCanvas3D.cpp | 2 +- src/slic3r/GUI/GLCanvas3D.hpp | 2 +- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index b9a7d2338..092ddbfd8 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -757,12 +757,12 @@ void GCodeViewer::reset() #endif // ENABLE_GCODE_VIEWER_STATISTICS } -void GCodeViewer::render() const +void GCodeViewer::render() { auto init_gl_data = [this]() { // initializes opengl data of TBuffers for (size_t i = 0; i < m_buffers.size(); ++i) { - TBuffer& buffer = const_cast(m_buffers[i]); + TBuffer& buffer = m_buffers[i]; switch (buffer_type(i)) { default: { break; } @@ -789,17 +789,17 @@ void GCodeViewer::render() const } // initializes tool marker - const_cast(&m_sequential_view)->marker.init(); + m_sequential_view.marker.init(); // initializes point sizes std::array point_sizes; ::glGetIntegerv(GL_ALIASED_POINT_SIZE_RANGE, point_sizes.data()); - *const_cast*>(&m_detected_point_sizes) = { static_cast(point_sizes[0]), static_cast(point_sizes[1]) }; - *const_cast(&m_gl_data_initialized) = true; + m_detected_point_sizes = { static_cast(point_sizes[0]), static_cast(point_sizes[1]) }; + m_gl_data_initialized = true; }; #if ENABLE_GCODE_VIEWER_STATISTICS - const_cast(&m_statistics)->reset_opengl(); + m_statistics.reset_opengl(); #endif // ENABLE_GCODE_VIEWER_STATISTICS // OpenGL data must be initialized after the glContext has been created. @@ -815,10 +815,9 @@ void GCodeViewer::render() const render_shells(); float legend_height = 0.0f; render_legend(legend_height); - SequentialView* sequential_view = const_cast(&m_sequential_view); - if (sequential_view->current.last != sequential_view->endpoints.last) { - sequential_view->marker.set_world_position(sequential_view->current_position); - sequential_view->render(legend_height); + if (m_sequential_view.current.last != m_sequential_view.endpoints.last) { + m_sequential_view.marker.set_world_position(m_sequential_view.current_position); + m_sequential_view.render(legend_height); } #if ENABLE_GCODE_VIEWER_STATISTICS render_statistics(); @@ -2360,7 +2359,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool #endif // ENABLE_GCODE_VIEWER_STATISTICS } -void GCodeViewer::render_toolpaths() const +void GCodeViewer::render_toolpaths() { #if ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS float point_size = 20.0f; @@ -2404,7 +2403,7 @@ void GCodeViewer::render_toolpaths() const set_uniform_color(path.color, shader); glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); #if ENABLE_GCODE_VIEWER_STATISTICS - ++const_cast(&m_statistics)->gl_multi_points_calls_count; + ++m_statistics.gl_multi_points_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS } } @@ -2425,7 +2424,7 @@ void GCodeViewer::render_toolpaths() const set_uniform_color(path.color, shader); glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); #if ENABLE_GCODE_VIEWER_STATISTICS - ++const_cast(&m_statistics)->gl_multi_lines_calls_count; + ++m_statistics.gl_multi_lines_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS } } @@ -2442,7 +2441,7 @@ void GCodeViewer::render_toolpaths() const set_uniform_color(path.color, shader); glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); #if ENABLE_GCODE_VIEWER_STATISTICS - ++const_cast(&m_statistics)->gl_multi_triangles_calls_count; + ++m_statistics.gl_multi_triangles_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS } } @@ -2535,7 +2534,7 @@ void GCodeViewer::render_toolpaths() const glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); #if ENABLE_GCODE_VIEWER_STATISTICS - ++const_cast(&m_statistics)->gl_triangles_calls_count; + ++m_statistics.gl_triangles_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS if (has_normals) @@ -2554,7 +2553,7 @@ void GCodeViewer::render_toolpaths() const } } -void GCodeViewer::render_shells() const +void GCodeViewer::render_shells() { if (!m_shells.visible || m_shells.volumes.empty()) return; @@ -2572,7 +2571,7 @@ void GCodeViewer::render_shells() const // glsafe(::glDepthMask(GL_TRUE)); } -void GCodeViewer::render_legend(float& legend_height) const +void GCodeViewer::render_legend(float& legend_height) { if (!m_legend_enabled) return; @@ -2935,8 +2934,7 @@ void GCodeViewer::render_legend(float& legend_height) const const bool visible = is_visible(role); append_item(EItemType::Rect, Extrusion_Role_Colors[static_cast(role)], labels[i], visible, times[i], percents[i], max_percent, offsets, used_filaments_m[i], used_filaments_g[i], [this, role, visible]() { - Extrusions* extrusions = const_cast(&m_extrusions); - extrusions->role_visibility_flags = visible ? extrusions->role_visibility_flags & ~(1 << role) : extrusions->role_visibility_flags | (1 << role); + m_extrusions.role_visibility_flags = visible ? m_extrusions.role_visibility_flags & ~(1 << role) : m_extrusions.role_visibility_flags | (1 << role); // update buffers' render paths refresh_render_paths(false, false); wxGetApp().plater()->update_preview_moves_slider(); @@ -3408,7 +3406,7 @@ void GCodeViewer::render_legend(float& legend_height) const auto show_mode_button = [this, &imgui, can_show_mode_button](const wxString& label, PrintEstimatedStatistics::ETimeMode mode) { if (can_show_mode_button(mode)) { if (imgui.button(label)) { - *const_cast(&m_time_estimate_mode) = mode; + m_time_estimate_mode = mode; wxGetApp().plater()->get_current_canvas3D()->set_as_dirty(); wxGetApp().plater()->get_current_canvas3D()->request_extra_frame(); } @@ -3435,7 +3433,7 @@ void GCodeViewer::render_legend(float& legend_height) const } #if ENABLE_GCODE_VIEWER_STATISTICS -void GCodeViewer::render_statistics() const +void GCodeViewer::render_statistics() { static const float offset = 275.0f; diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 41307bad9..ecdffc5fe 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -632,7 +632,7 @@ public: void update_shells_color_by_extruder(const DynamicPrintConfig* config); void reset(); - void render() const; + void render(); bool has_data() const { return !m_roles.empty(); } bool can_export_toolpaths() const; @@ -678,11 +678,11 @@ private: void load_toolpaths(const GCodeProcessor::Result& gcode_result); void load_shells(const Print& print, bool initialized); void refresh_render_paths(bool keep_sequential_current_first, bool keep_sequential_current_last) const; - void render_toolpaths() const; - void render_shells() const; - void render_legend(float& legend_height) const; + void render_toolpaths(); + void render_shells(); + void render_legend(float& legend_height); #if ENABLE_GCODE_VIEWER_STATISTICS - void render_statistics() const; + void render_statistics(); #endif // ENABLE_GCODE_VIEWER_STATISTICS bool is_visible(ExtrusionRole role) const { return role < erCount && (m_extrusions.role_visibility_flags & (1 << role)) != 0; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index e2699fb6d..1e0cb0a32 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5175,7 +5175,7 @@ void GLCanvas3D::_render_objects() m_camera_clipping_plane = ClippingPlane::ClipsNothing(); } -void GLCanvas3D::_render_gcode() const +void GLCanvas3D::_render_gcode() { m_gcode_viewer.render(); } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index d9cd55e35..7cdaac1a6 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -906,7 +906,7 @@ private: #else void _render_objects(); #endif // ENABLE_DELAYED_TRANSPARENT_VOLUMES_RENDERING - void _render_gcode() const; + void _render_gcode(); void _render_selection() const; void _render_sequential_clearance(); #if ENABLE_RENDER_SELECTION_CENTER From 329f9a77c2084a815708492fd0a61ca963f63fce Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 4 Aug 2021 13:27:42 +0200 Subject: [PATCH 03/60] Colors defined as std::array in GCodeViewer --- src/slic3r/GUI/GCodeViewer.cpp | 165 +++++++++++++++++---------------- src/slic3r/GUI/GCodeViewer.hpp | 6 +- 2 files changed, 90 insertions(+), 81 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 092ddbfd8..055fb6fab 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -44,10 +44,10 @@ static EMoveType buffer_type(unsigned char id) { return static_cast(static_cast(EMoveType::Retract) + id); } -static std::array decode_color(const std::string& color) { +static std::array decode_color(const std::string& color) { static const float INV_255 = 1.0f / 255.0f; - std::array ret = { 0.0f, 0.0f, 0.0f }; + std::array ret = { 0.0f, 0.0f, 0.0f, 1.0f }; const char* c = color.data() + 1; if (color.size() == 7 && color.front() == '#') { for (size_t j = 0; j < 3; ++j) { @@ -62,8 +62,8 @@ static std::array decode_color(const std::string& color) { return ret; } -static std::vector> decode_colors(const std::vector& colors) { - std::vector> output(colors.size(), { 0.0f, 0.0f, 0.0f }); +static std::vector> decode_colors(const std::vector& colors) { + std::vector> output(colors.size(), { 0.0f, 0.0f, 0.0f, 1.0f }); for (size_t i = 0; i < colors.size(); ++i) { output[i] = decode_color(colors[i]); } @@ -176,7 +176,7 @@ GCodeViewer::Color GCodeViewer::Extrusions::Range::get_color_at(float value) con const float local_t = std::clamp(global_t - static_cast(color_low_idx), 0.0f, 1.0f); // Interpolate between the low and high colors to find exactly which color the input value should get - Color ret; + Color ret = { 0.0f, 0.0f, 0.0f, 1.0f }; for (unsigned int i = 0; i < 3; ++i) { ret[i] = lerp(Range_Colors[color_low_idx][i], Range_Colors[color_high_idx][i], local_t); } @@ -195,7 +195,7 @@ void GCodeViewer::SequentialRangeCap::reset() { buffer = nullptr; ibo = 0; vbo = 0; - color = { 0.0f, 0.0f, 0.0f }; + color = { 0.0f, 0.0f, 0.0f, 1.0f }; } void GCodeViewer::SequentialView::Marker::init() @@ -484,56 +484,57 @@ void GCodeViewer::SequentialView::render(float legend_height) const } const std::vector GCodeViewer::Extrusion_Role_Colors {{ - { 0.75f, 0.75f, 0.75f }, // erNone - { 1.00f, 0.90f, 0.30f }, // erPerimeter - { 1.00f, 0.49f, 0.22f }, // erExternalPerimeter - { 0.12f, 0.12f, 1.00f }, // erOverhangPerimeter - { 0.69f, 0.19f, 0.16f }, // erInternalInfill - { 0.59f, 0.33f, 0.80f }, // erSolidInfill - { 0.94f, 0.25f, 0.25f }, // erTopSolidInfill - { 1.00f, 0.55f, 0.41f }, // erIroning - { 0.30f, 0.50f, 0.73f }, // erBridgeInfill - { 1.00f, 1.00f, 1.00f }, // erGapFill - { 0.00f, 0.53f, 0.43f }, // erSkirt - { 0.00f, 1.00f, 0.00f }, // erSupportMaterial - { 0.00f, 0.50f, 0.00f }, // erSupportMaterialInterface - { 0.70f, 0.89f, 0.67f }, // erWipeTower - { 0.37f, 0.82f, 0.58f }, // erCustom - { 0.00f, 0.00f, 0.00f } // erMixed + { 0.75f, 0.75f, 0.75f, 1.0f }, // erNone + { 1.00f, 0.90f, 0.30f, 1.0f }, // erPerimeter + { 1.00f, 0.49f, 0.22f, 1.0f }, // erExternalPerimeter + { 0.12f, 0.12f, 1.00f, 1.0f }, // erOverhangPerimeter + { 0.69f, 0.19f, 0.16f, 1.0f }, // erInternalInfill + { 0.59f, 0.33f, 0.80f, 1.0f }, // erSolidInfill + { 0.94f, 0.25f, 0.25f, 1.0f }, // erTopSolidInfill + { 1.00f, 0.55f, 0.41f, 1.0f }, // erIroning + { 0.30f, 0.50f, 0.73f, 1.0f }, // erBridgeInfill + { 1.00f, 1.00f, 1.00f, 1.0f }, // erGapFill + { 0.00f, 0.53f, 0.43f, 1.0f }, // erSkirt + { 0.00f, 1.00f, 0.00f, 1.0f }, // erSupportMaterial + { 0.00f, 0.50f, 0.00f, 1.0f }, // erSupportMaterialInterface + { 0.70f, 0.89f, 0.67f, 1.0f }, // erWipeTower + { 0.37f, 0.82f, 0.58f, 1.0f }, // erCustom + { 0.00f, 0.00f, 0.00f, 1.0f } // erMixed }}; const std::vector GCodeViewer::Options_Colors {{ - { 0.803f, 0.135f, 0.839f }, // Retractions - { 0.287f, 0.679f, 0.810f }, // Unretractions - { 0.900f, 0.900f, 0.900f }, // Seams - { 0.758f, 0.744f, 0.389f }, // ToolChanges - { 0.856f, 0.582f, 0.546f }, // ColorChanges - { 0.322f, 0.942f, 0.512f }, // PausePrints - { 0.886f, 0.825f, 0.262f } // CustomGCodes + { 0.803f, 0.135f, 0.839f, 1.0f }, // Retractions + { 0.287f, 0.679f, 0.810f, 1.0f }, // Unretractions + { 0.900f, 0.900f, 0.900f, 1.0f }, // Seams + { 0.758f, 0.744f, 0.389f, 1.0f }, // ToolChanges + { 0.856f, 0.582f, 0.546f, 1.0f }, // ColorChanges + { 0.322f, 0.942f, 0.512f, 1.0f }, // PausePrints + { 0.886f, 0.825f, 0.262f, 1.0f } // CustomGCodes }}; const std::vector GCodeViewer::Travel_Colors {{ - { 0.219f, 0.282f, 0.609f }, // Move - { 0.112f, 0.422f, 0.103f }, // Extrude - { 0.505f, 0.064f, 0.028f } // Retract + { 0.219f, 0.282f, 0.609f, 1.0f }, // Move + { 0.112f, 0.422f, 0.103f, 1.0f }, // Extrude + { 0.505f, 0.064f, 0.028f, 1.0f } // Retract }}; -const GCodeViewer::Color GCodeViewer::Wipe_Color = { 1.0f, 1.0f, 0.0f }; - const std::vector GCodeViewer::Range_Colors {{ - { 0.043f, 0.173f, 0.478f }, // bluish - { 0.075f, 0.349f, 0.522f }, - { 0.110f, 0.533f, 0.569f }, - { 0.016f, 0.839f, 0.059f }, - { 0.667f, 0.949f, 0.000f }, - { 0.988f, 0.975f, 0.012f }, - { 0.961f, 0.808f, 0.039f }, - { 0.890f, 0.533f, 0.125f }, - { 0.820f, 0.408f, 0.188f }, - { 0.761f, 0.322f, 0.235f }, - { 0.581f, 0.149f, 0.087f } // reddish + { 0.043f, 0.173f, 0.478f, 1.0f }, // bluish + { 0.075f, 0.349f, 0.522f, 1.0f }, + { 0.110f, 0.533f, 0.569f, 1.0f }, + { 0.016f, 0.839f, 0.059f, 1.0f }, + { 0.667f, 0.949f, 0.000f, 1.0f }, + { 0.988f, 0.975f, 0.012f, 1.0f }, + { 0.961f, 0.808f, 0.039f, 1.0f }, + { 0.890f, 0.533f, 0.125f, 1.0f }, + { 0.820f, 0.408f, 0.188f, 1.0f }, + { 0.761f, 0.322f, 0.235f, 1.0f }, + { 0.581f, 0.149f, 0.087f, 1.0f } // reddish }}; +const GCodeViewer::Color GCodeViewer::Wipe_Color = { 1.0f, 1.0f, 0.0f, 1.0f }; +const GCodeViewer::Color GCodeViewer::Neutral_Color = { 0.25f, 0.25f, 0.25f, 1.0f }; + GCodeViewer::GCodeViewer() { // initializes non OpenGL data of TBuffers @@ -1967,18 +1968,14 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool case EViewType::VolumetricRate: { color = m_extrusions.ranges.volumetric_rate.get_color_at(path.volumetric_rate); break; } case EViewType::Tool: { color = m_tool_colors[path.extruder_id]; break; } case EViewType::ColorPrint: { - if (path.cp_color_id >= static_cast(m_tool_colors.size())) { - color = { 0.5f, 0.5f, 0.5f }; -// // complementary color -// color = m_tool_colors[255 - path.cp_color_id]; -// color = { 1.0f - color[0], 1.0f - color[1], 1.0f - color[2] }; - } + if (path.cp_color_id >= static_cast(m_tool_colors.size())) + color = { 0.5f, 0.5f, 0.5f, 1.0f }; else color = m_tool_colors[path.cp_color_id]; break; } - default: { color = { 1.0f, 1.0f, 1.0f }; break; } + default: { color = { 1.0f, 1.0f, 1.0f, 1.0f }; break; } } return color; @@ -2142,20 +2139,20 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool Color color; switch (path.type) { - case EMoveType::Tool_change: { color = Options_Colors[static_cast(EOptionsColors::ToolChanges)]; break; } - case EMoveType::Color_change: { color = Options_Colors[static_cast(EOptionsColors::ColorChanges)]; break; } - case EMoveType::Pause_Print: { color = Options_Colors[static_cast(EOptionsColors::PausePrints)]; break; } - case EMoveType::Custom_GCode: { color = Options_Colors[static_cast(EOptionsColors::CustomGCodes)]; break; } - case EMoveType::Retract: { color = Options_Colors[static_cast(EOptionsColors::Retractions)]; break; } - case EMoveType::Unretract: { color = Options_Colors[static_cast(EOptionsColors::Unretractions)]; break; } - case EMoveType::Seam: { color = Options_Colors[static_cast(EOptionsColors::Seams)]; break; } + case EMoveType::Tool_change: + case EMoveType::Color_change: + case EMoveType::Pause_Print: + case EMoveType::Custom_GCode: + case EMoveType::Retract: + case EMoveType::Unretract: + case EMoveType::Seam: { color = option_color(path.type); break; } case EMoveType::Extrude: { if (!top_layer_only || m_sequential_view.current.last == global_endpoints.last || is_in_layers_range(path, m_layers_z_range[1], m_layers_z_range[1])) color = extrusion_color(path); else - color = { 0.25f, 0.25f, 0.25f }; + color = Neutral_Color; break; } @@ -2163,12 +2160,12 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool if (!top_layer_only || m_sequential_view.current.last == global_endpoints.last || is_travel_in_layers_range(path_id, m_layers_z_range[1], m_layers_z_range[1])) color = (m_view_type == EViewType::Feedrate || m_view_type == EViewType::Tool || m_view_type == EViewType::ColorPrint) ? extrusion_color(path) : travel_color(path); else - color = { 0.25f, 0.25f, 0.25f }; + color = Neutral_Color; break; } case EMoveType::Wipe: { color = Wipe_Color; break; } - default: { color = { 0.0f, 0.0f, 0.0f }; break; } + default: { color = { 0.0f, 0.0f, 0.0f, 1.0f }; break; } } RenderPath key{ tbuffer_id, color, static_cast(ibuffer_id), path_id }; @@ -2373,15 +2370,10 @@ void GCodeViewer::render_toolpaths() float near_plane_height = camera.get_type() == Camera::EType::Perspective ? static_cast(viewport[3]) / (2.0f * static_cast(2.0 * std::tan(0.5 * Geometry::deg2rad(camera.get_fov())))) : static_cast(viewport[3]) * 0.0005; - auto set_uniform_color = [](const std::array& color, GLShaderProgram& shader) { - std::array color4 = { color[0], color[1], color[2], 1.0f }; - shader.set_uniform("uniform_color", color4); - }; - #if ENABLE_GCODE_VIEWER_STATISTICS - auto render_as_points = [this, zoom, point_size, near_plane_height, set_uniform_color] + auto render_as_points = [this, zoom, point_size, near_plane_height] #else - auto render_as_points = [zoom, point_size, near_plane_height, set_uniform_color] + auto render_as_points = [zoom, point_size, near_plane_height] #endif // ENABLE_GCODE_VIEWER_STATISTICS (const TBuffer& buffer, unsigned int ibuffer_id, GLShaderProgram& shader) { #if ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS @@ -2400,7 +2392,7 @@ void GCodeViewer::render_toolpaths() for (const RenderPath& path : buffer.render_paths) { if (path.ibuffer_id == ibuffer_id) { - set_uniform_color(path.color, shader); + shader.set_uniform("uniform_color", path.color); glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_multi_points_calls_count; @@ -2413,15 +2405,15 @@ void GCodeViewer::render_toolpaths() }; #if ENABLE_GCODE_VIEWER_STATISTICS - auto render_as_lines = [this, light_intensity, set_uniform_color] + auto render_as_lines = [this, light_intensity] #else - auto render_as_lines = [light_intensity, set_uniform_color] + auto render_as_lines = [light_intensity] #endif // ENABLE_GCODE_VIEWER_STATISTICS (const TBuffer& buffer, unsigned int ibuffer_id, GLShaderProgram& shader) { shader.set_uniform("light_intensity", light_intensity); for (const RenderPath& path : buffer.render_paths) { if (path.ibuffer_id == ibuffer_id) { - set_uniform_color(path.color, shader); + shader.set_uniform("uniform_color", path.color); glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_multi_lines_calls_count; @@ -2431,14 +2423,14 @@ void GCodeViewer::render_toolpaths() }; #if ENABLE_GCODE_VIEWER_STATISTICS - auto render_as_triangles = [this, set_uniform_color] + auto render_as_triangles = [this] #else - auto render_as_triangles = [set_uniform_color] + auto render_as_triangles = [] #endif // ENABLE_GCODE_VIEWER_STATISTICS (const TBuffer& buffer, unsigned int ibuffer_id, GLShaderProgram& shader) { for (const RenderPath& path : buffer.render_paths) { if (path.ibuffer_id == ibuffer_id) { - set_uniform_color(path.color, shader); + shader.set_uniform("uniform_color", path.color); glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_multi_triangles_calls_count; @@ -2509,9 +2501,9 @@ void GCodeViewer::render_toolpaths() } #if ENABLE_GCODE_VIEWER_STATISTICS - auto render_sequential_range_cap = [this, set_uniform_color] + auto render_sequential_range_cap = [this] #else - auto render_sequential_range_cap = [set_uniform_color] + auto render_sequential_range_cap = [] #endif // ENABLE_GCODE_VIEWER_STATISTICS (const SequentialRangeCap& cap) { GLShaderProgram* shader = wxGetApp().get_shader(cap.buffer->shader.c_str()); @@ -2527,7 +2519,7 @@ void GCodeViewer::render_toolpaths() glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); } - set_uniform_color(cap.color, *shader); + shader->set_uniform("uniform_color", cap.color); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cap.ibo)); glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)cap.indices_count(), GL_UNSIGNED_SHORT, nullptr)); @@ -3548,6 +3540,21 @@ void GCodeViewer::log_memory_used(const std::string& label, int64_t additional) } } +GCodeViewer::Color GCodeViewer::option_color(EMoveType move_type) const +{ + switch (move_type) + { + case EMoveType::Tool_change: { return Options_Colors[static_cast(EOptionsColors::ToolChanges)]; } + case EMoveType::Color_change: { return Options_Colors[static_cast(EOptionsColors::ColorChanges)]; } + case EMoveType::Pause_Print: { return Options_Colors[static_cast(EOptionsColors::PausePrints)]; } + case EMoveType::Custom_GCode: { return Options_Colors[static_cast(EOptionsColors::CustomGCodes)]; } + case EMoveType::Retract: { return Options_Colors[static_cast(EOptionsColors::Retractions)]; } + case EMoveType::Unretract: { return Options_Colors[static_cast(EOptionsColors::Unretractions)]; } + case EMoveType::Seam: { return Options_Colors[static_cast(EOptionsColors::Seams)]; } + default: { return { 0.0f, 0.0f, 0.0f, 1.0f }; } + } +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index ecdffc5fe..3d9b9bb69 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -22,7 +22,7 @@ namespace GUI { class GCodeViewer { using IBufferType = unsigned short; - using Color = std::array; + using Color = std::array; using VertexBuffer = std::vector; using MultiVertexBuffer = std::vector; using IndexBuffer = std::vector; @@ -31,8 +31,9 @@ class GCodeViewer static const std::vector Extrusion_Role_Colors; static const std::vector Options_Colors; static const std::vector Travel_Colors; - static const Color Wipe_Color; static const std::vector Range_Colors; + static const Color Wipe_Color; + static const Color Neutral_Color; enum class EOptionsColors : unsigned char { @@ -689,6 +690,7 @@ private: } bool is_visible(const Path& path) const { return is_visible(path.role); } void log_memory_used(const std::string& label, int64_t additional = 0) const; + Color option_color(EMoveType move_type) const; }; } // namespace GUI From 93db27f40c7f655e65ebff29fd67eddfb561940b Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 4 Aug 2021 13:49:51 +0200 Subject: [PATCH 04/60] A bit of refactoring into GCodeViewer --- src/slic3r/GUI/GCodeViewer.cpp | 200 ++++++++++++++++----------------- 1 file changed, 100 insertions(+), 100 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 055fb6fab..c5109f07e 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -125,7 +125,7 @@ bool GCodeViewer::Path::matches(const GCodeProcessor::MoveVertex& move) const case EMoveType::Extrude: { // use rounding to reduce the number of generated paths return type == move.type && extruder_id == move.extruder_id && cp_color_id == move.cp_color_id && role == move.extrusion_role && - move.position[2] <= sub_paths.front().first.position[2] && feedrate == move.feedrate && fan_speed == move.fan_speed && + move.position.z() <= sub_paths.front().first.position.z() && feedrate == move.feedrate && fan_speed == move.fan_speed && height == round_to_nearest(move.height, 2) && width == round_to_nearest(move.width, 2) && matches_percent(volumetric_rate, move.volumetric_rate(), 0.05f); } @@ -207,7 +207,7 @@ void GCodeViewer::SequentialView::Marker::init() void GCodeViewer::SequentialView::Marker::set_world_position(const Vec3f& position) { m_world_position = position; - m_world_transform = (Geometry::assemble_transform((position + m_z_offset * Vec3f::UnitZ()).cast()) * Geometry::assemble_transform(m_model.get_bounding_box().size()[2] * Vec3d::UnitZ(), { M_PI, 0.0, 0.0 })).cast(); + m_world_transform = (Geometry::assemble_transform((position + m_z_offset * Vec3f::UnitZ()).cast()) * Geometry::assemble_transform(m_model.get_bounding_box().size().z() * Vec3d::UnitZ(), { M_PI, 0.0, 0.0 })).cast(); } void GCodeViewer::SequentialView::Marker::render() const @@ -623,23 +623,23 @@ void GCodeViewer::load(const GCodeProcessor::Result& gcode_result, const Print& else { // adjust printbed size in dependence of toolpaths bbox const double margin = 10.0; - Vec2d min(m_paths_bounding_box.min(0) - margin, m_paths_bounding_box.min(1) - margin); - Vec2d max(m_paths_bounding_box.max(0) + margin, m_paths_bounding_box.max(1) + margin); + Vec2d min(m_paths_bounding_box.min.x() - margin, m_paths_bounding_box.min.y() - margin); + Vec2d max(m_paths_bounding_box.max.x() + margin, m_paths_bounding_box.max.y() + margin); Vec2d size = max - min; bed_shape = { - { min(0), min(1) }, - { max(0), min(1) }, - { max(0), min(1) + 0.442265 * size[1]}, - { max(0) - 10.0, min(1) + 0.4711325 * size[1]}, - { max(0) + 10.0, min(1) + 0.5288675 * size[1]}, - { max(0), min(1) + 0.557735 * size[1]}, - { max(0), max(1) }, - { min(0) + 0.557735 * size[0], max(1)}, - { min(0) + 0.5288675 * size[0], max(1) - 10.0}, - { min(0) + 0.4711325 * size[0], max(1) + 10.0}, - { min(0) + 0.442265 * size[0], max(1)}, - { min(0), max(1) } }; + { min.x(), min.y() }, + { max.x(), min.y() }, + { max.x(), min.y() + 0.442265 * size.y()}, + { max.x() - 10.0, min.y() + 0.4711325 * size.y()}, + { max.x() + 10.0, min.y() + 0.5288675 * size.y()}, + { max.x(), min.y() + 0.557735 * size.y()}, + { max.x(), max.y() }, + { min.x() + 0.557735 * size.x(), max.y()}, + { min.x() + 0.5288675 * size.x(), max.y() - 10.0}, + { min.x() + 0.4711325 * size.x(), max.y() + 10.0}, + { min.x() + 0.442265 * size.x(), max.y()}, + { min.x(), max.y() } }; } wxGetApp().plater()->set_bed_shape(bed_shape, texture, model, gcode_result.bed_shape.empty()); @@ -1036,13 +1036,13 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const // save vertices to file fprintf(fp, "\n# vertices\n"); for (const Vec3f& v : out_vertices) { - fprintf(fp, "v %g %g %g\n", v[0], v[1], v[2]); + fprintf(fp, "v %g %g %g\n", v.x(), v.y(), v.x()); } // save normals to file fprintf(fp, "\n# normals\n"); for (const Vec3f& n : out_normals) { - fprintf(fp, "vn %g %g %g\n", n[0], n[1], n[2]); + fprintf(fp, "vn %g %g %g\n", n.x(), n.y(), n.z()); } size_t i = 0; @@ -1124,9 +1124,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // format data into the buffers to be rendered as points auto add_vertices_as_point = [](const GCodeProcessor::MoveVertex& curr, VertexBuffer& vertices) { - vertices.push_back(curr.position[0]); - vertices.push_back(curr.position[1]); - vertices.push_back(curr.position[2]); + vertices.push_back(curr.position.x()); + vertices.push_back(curr.position.y()); + vertices.push_back(curr.position.z()); }; auto add_indices_as_point = [](const GCodeProcessor::MoveVertex& curr, TBuffer& buffer, unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id) { @@ -1137,13 +1137,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // format data into the buffers to be rendered as lines auto add_vertices_as_line = [](const GCodeProcessor::MoveVertex& prev, const GCodeProcessor::MoveVertex& curr, VertexBuffer& vertices) { // x component of the normal to the current segment (the normal is parallel to the XY plane) - float normal_x = (curr.position - prev.position).normalized()[1]; + const float normal_x = (curr.position - prev.position).normalized().y(); auto add_vertex = [&vertices, normal_x](const GCodeProcessor::MoveVertex& vertex) { // add position - vertices.push_back(vertex.position[0]); - vertices.push_back(vertex.position[1]); - vertices.push_back(vertex.position[2]); + vertices.push_back(vertex.position.x()); + vertices.push_back(vertex.position.y()); + vertices.push_back(vertex.position.z()); // add normal x component vertices.push_back(normal_x); }; @@ -1177,13 +1177,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) auto add_vertices_as_solid = [](const GCodeProcessor::MoveVertex& prev, const GCodeProcessor::MoveVertex& curr, TBuffer& buffer, unsigned int vbuffer_id, VertexBuffer& vertices, size_t move_id) { auto store_vertex = [](VertexBuffer& vertices, const Vec3f& position, const Vec3f& normal) { // append position - vertices.push_back(position[0]); - vertices.push_back(position[1]); - vertices.push_back(position[2]); + vertices.push_back(position.x()); + vertices.push_back(position.y()); + vertices.push_back(position.z()); // append normal - vertices.push_back(normal[0]); - vertices.push_back(normal[1]); - vertices.push_back(normal[2]); + vertices.push_back(normal.x()); + vertices.push_back(normal.y()); + vertices.push_back(normal.z()); }; if (prev.type != curr.type || !buffer.paths.back().matches(curr)) { @@ -1193,19 +1193,19 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) Path& last_path = buffer.paths.back(); - Vec3f dir = (curr.position - prev.position).normalized(); - Vec3f right = Vec3f(dir[1], -dir[0], 0.0f).normalized(); - Vec3f left = -right; - Vec3f up = right.cross(dir); - Vec3f down = -up; - float half_width = 0.5f * last_path.width; - float half_height = 0.5f * last_path.height; - Vec3f prev_pos = prev.position - half_height * up; - Vec3f curr_pos = curr.position - half_height * up; - Vec3f d_up = half_height * up; - Vec3f d_down = -half_height * up; - Vec3f d_right = half_width * right; - Vec3f d_left = -half_width * right; + const Vec3f dir = (curr.position - prev.position).normalized(); + const Vec3f right = Vec3f(dir.y(), -dir.x(), 0.0f).normalized(); + const Vec3f left = -right; + const Vec3f up = right.cross(dir); + const Vec3f down = -up; + const float half_width = 0.5f * last_path.width; + const float half_height = 0.5f * last_path.height; + const Vec3f prev_pos = prev.position - half_height * up; + const Vec3f curr_pos = curr.position - half_height * up; + const Vec3f d_up = half_height * up; + const Vec3f d_down = -half_height * up; + const Vec3f d_right = half_width * right; + const Vec3f d_left = -half_width * right; // vertices 1st endpoint if (last_path.vertices_count() == 1 || vertices.empty()) { @@ -1284,14 +1284,14 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) Path& last_path = buffer.paths.back(); - Vec3f dir = (curr.position - prev.position).normalized(); - Vec3f right = Vec3f(dir[1], -dir[0], 0.0f).normalized(); - Vec3f up = right.cross(dir); - float sq_length = (curr.position - prev.position).squaredNorm(); + const Vec3f dir = (curr.position - prev.position).normalized(); + const Vec3f right = Vec3f(dir.y(), -dir.x(), 0.0f).normalized(); + const Vec3f up = right.cross(dir); + const float sq_length = (curr.position - prev.position).squaredNorm(); const std::array first_seg_v_offsets = convert_vertices_offset(vbuffer_size, { 0, 1, 2, 3, 4, 5, 6, 7 }); const std::array non_first_seg_v_offsets = convert_vertices_offset(vbuffer_size, { -4, 0, -2, 1, 2, 3, 4, 5 }); - bool is_first_segment = (last_path.vertices_count() == 1); + const bool is_first_segment = (last_path.vertices_count() == 1); if (is_first_segment || vbuffer_size == 0) { // 1st segment or restart into a new vertex buffer // =============================================== @@ -1310,20 +1310,20 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // any other segment // ================= float displacement = 0.0f; - float cos_dir = prev_dir.dot(dir); + const float cos_dir = prev_dir.dot(dir); if (cos_dir > -0.9998477f) { // if the angle between adjacent segments is smaller than 179 degrees - Vec3f med_dir = (prev_dir + dir).normalized(); - float half_width = 0.5f * last_path.width; + const Vec3f med_dir = (prev_dir + dir).normalized(); + const float half_width = 0.5f * last_path.width; displacement = half_width * ::tan(::acos(std::clamp(dir.dot(med_dir), -1.0f, 1.0f))); } - float sq_displacement = sqr(displacement); - bool can_displace = displacement > 0.0f && sq_displacement < sq_prev_length && sq_displacement < sq_length; + const float sq_displacement = sqr(displacement); + const bool can_displace = displacement > 0.0f && sq_displacement < sq_prev_length && sq_displacement < sq_length; - bool is_right_turn = prev_up.dot(prev_dir.cross(dir)) <= 0.0f; + const bool is_right_turn = prev_up.dot(prev_dir.cross(dir)) <= 0.0f; // whether the angle between adjacent segments is greater than 45 degrees - bool is_sharp = cos_dir < 0.7071068f; + const bool is_sharp = cos_dir < 0.7071068f; bool right_displaced = false; bool left_displaced = false; @@ -1434,7 +1434,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) progress_count = 0; } - unsigned char id = buffer_id(curr.type); + const unsigned char id = buffer_id(curr.type); TBuffer& t_buffer = m_buffers[id]; MultiVertexBuffer& v_multibuffer = vertices[id]; @@ -1476,24 +1476,24 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) return Vec3f(vertices[offset + 0], vertices[offset + 1], vertices[offset + 2]); }; auto update_position_at = [](VertexBuffer& vertices, size_t offset, const Vec3f& position) { - vertices[offset + 0] = position[0]; - vertices[offset + 1] = position[1]; - vertices[offset + 2] = position[2]; + vertices[offset + 0] = position.x(); + vertices[offset + 1] = position.y(); + vertices[offset + 2] = position.z(); }; auto match_right_vertices = [&](const Path::Sub_Path& prev_sub_path, const Path::Sub_Path& next_sub_path, size_t curr_s_id, size_t vertex_size_floats, const Vec3f& displacement_vec) { if (&prev_sub_path == &next_sub_path) { // previous and next segment are both contained into to the same vertex buffer VertexBuffer& vbuffer = v_multibuffer[prev_sub_path.first.b_id]; // offset into the vertex buffer of the next segment 1st vertex - size_t next_1st_offset = (prev_sub_path.last.s_id - curr_s_id) * 6 * vertex_size_floats; + const size_t next_1st_offset = (prev_sub_path.last.s_id - curr_s_id) * 6 * vertex_size_floats; // offset into the vertex buffer of the right vertex of the previous segment - size_t prev_right_offset = prev_sub_path.last.i_id - next_1st_offset - 3 * vertex_size_floats; + const size_t prev_right_offset = prev_sub_path.last.i_id - next_1st_offset - 3 * vertex_size_floats; // new position of the right vertices - Vec3f shared_vertex = extract_position_at(vbuffer, prev_right_offset) + displacement_vec; + const Vec3f shared_vertex = extract_position_at(vbuffer, prev_right_offset) + displacement_vec; // update previous segment update_position_at(vbuffer, prev_right_offset, shared_vertex); // offset into the vertex buffer of the right vertex of the next segment - size_t next_right_offset = next_sub_path.last.i_id - next_1st_offset; + const size_t next_right_offset = next_sub_path.last.i_id - next_1st_offset; // update next segment update_position_at(vbuffer, next_right_offset, shared_vertex); } @@ -1501,13 +1501,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) VertexBuffer& prev_vbuffer = v_multibuffer[prev_sub_path.first.b_id]; VertexBuffer& next_vbuffer = v_multibuffer[next_sub_path.first.b_id]; // offset into the previous vertex buffer of the right vertex of the previous segment - size_t prev_right_offset = prev_sub_path.last.i_id - 3 * vertex_size_floats; + const size_t prev_right_offset = prev_sub_path.last.i_id - 3 * vertex_size_floats; // new position of the right vertices - Vec3f shared_vertex = extract_position_at(prev_vbuffer, prev_right_offset) + displacement_vec; + const Vec3f shared_vertex = extract_position_at(prev_vbuffer, prev_right_offset) + displacement_vec; // update previous segment update_position_at(prev_vbuffer, prev_right_offset, shared_vertex); // offset into the next vertex buffer of the right vertex of the next segment - size_t next_right_offset = next_sub_path.first.i_id + 1 * vertex_size_floats; + const size_t next_right_offset = next_sub_path.first.i_id + 1 * vertex_size_floats; // update next segment update_position_at(next_vbuffer, next_right_offset, shared_vertex); } @@ -1517,15 +1517,15 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) if (&prev_sub_path == &next_sub_path) { // previous and next segment are both contained into to the same vertex buffer VertexBuffer& vbuffer = v_multibuffer[prev_sub_path.first.b_id]; // offset into the vertex buffer of the next segment 1st vertex - size_t next_1st_offset = (prev_sub_path.last.s_id - curr_s_id) * 6 * vertex_size_floats; + const size_t next_1st_offset = (prev_sub_path.last.s_id - curr_s_id) * 6 * vertex_size_floats; // offset into the vertex buffer of the left vertex of the previous segment - size_t prev_left_offset = prev_sub_path.last.i_id - next_1st_offset - 1 * vertex_size_floats; + const size_t prev_left_offset = prev_sub_path.last.i_id - next_1st_offset - 1 * vertex_size_floats; // new position of the left vertices - Vec3f shared_vertex = extract_position_at(vbuffer, prev_left_offset) + displacement_vec; + const Vec3f shared_vertex = extract_position_at(vbuffer, prev_left_offset) + displacement_vec; // update previous segment update_position_at(vbuffer, prev_left_offset, shared_vertex); // offset into the vertex buffer of the left vertex of the next segment - size_t next_left_offset = next_sub_path.last.i_id - next_1st_offset + 1 * vertex_size_floats; + const size_t next_left_offset = next_sub_path.last.i_id - next_1st_offset + 1 * vertex_size_floats; // update next segment update_position_at(vbuffer, next_left_offset, shared_vertex); } @@ -1533,13 +1533,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) VertexBuffer& prev_vbuffer = v_multibuffer[prev_sub_path.first.b_id]; VertexBuffer& next_vbuffer = v_multibuffer[next_sub_path.first.b_id]; // offset into the previous vertex buffer of the left vertex of the previous segment - size_t prev_left_offset = prev_sub_path.last.i_id - 1 * vertex_size_floats; + const size_t prev_left_offset = prev_sub_path.last.i_id - 1 * vertex_size_floats; // new position of the left vertices - Vec3f shared_vertex = extract_position_at(prev_vbuffer, prev_left_offset) + displacement_vec; + const Vec3f shared_vertex = extract_position_at(prev_vbuffer, prev_left_offset) + displacement_vec; // update previous segment update_position_at(prev_vbuffer, prev_left_offset, shared_vertex); // offset into the next vertex buffer of the left vertex of the next segment - size_t next_left_offset = next_sub_path.first.i_id + 3 * vertex_size_floats; + const size_t next_left_offset = next_sub_path.first.i_id + 3 * vertex_size_floats; // update next segment update_position_at(next_vbuffer, next_left_offset, shared_vertex); } @@ -1551,8 +1551,8 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // to two different vertex buffers size_t prev_sub_path_id = 0; size_t next_sub_path_id = 0; - size_t path_vertices_count = path.vertices_count(); - float half_width = 0.5f * path.width; + const size_t path_vertices_count = path.vertices_count(); + const float half_width = 0.5f * path.width; for (size_t j = 1; j < path_vertices_count - 1; ++j) { size_t curr_s_id = path.sub_paths.front().first.s_id + j; const Vec3f& prev = gcode_result.moves[curr_s_id - 1].position; @@ -1567,16 +1567,16 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) const Path::Sub_Path& prev_sub_path = path.sub_paths[prev_sub_path_id]; const Path::Sub_Path& next_sub_path = path.sub_paths[next_sub_path_id]; - Vec3f prev_dir = (curr - prev).normalized(); - Vec3f prev_right = Vec3f(prev_dir[1], -prev_dir[0], 0.0f).normalized(); - Vec3f prev_up = prev_right.cross(prev_dir); + const Vec3f prev_dir = (curr - prev).normalized(); + const Vec3f prev_right = Vec3f(prev_dir.y(), -prev_dir.x(), 0.0f).normalized(); + const Vec3f prev_up = prev_right.cross(prev_dir); - Vec3f next_dir = (next - curr).normalized(); + const Vec3f next_dir = (next - curr).normalized(); - bool is_right_turn = prev_up.dot(prev_dir.cross(next_dir)) <= 0.0f; - float cos_dir = prev_dir.dot(next_dir); + const bool is_right_turn = prev_up.dot(prev_dir.cross(next_dir)) <= 0.0f; + const float cos_dir = prev_dir.dot(next_dir); // whether the angle between adjacent segments is greater than 45 degrees - bool is_sharp = cos_dir < 0.7071068f; + const bool is_sharp = cos_dir < 0.7071068f; float displacement = 0.0f; if (cos_dir > -0.9998477f) { @@ -1585,10 +1585,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) displacement = half_width * ::tan(::acos(std::clamp(next_dir.dot(med_dir), -1.0f, 1.0f))); } - float sq_prev_length = (curr - prev).squaredNorm(); - float sq_next_length = (next - curr).squaredNorm(); - float sq_displacement = sqr(displacement); - bool can_displace = displacement > 0.0f && sq_displacement < sq_prev_length && sq_displacement < sq_next_length; + const float sq_prev_length = (curr - prev).squaredNorm(); + const float sq_next_length = (next - curr).squaredNorm(); + const float sq_displacement = sqr(displacement); + const bool can_displace = displacement > 0.0f && sq_displacement < sq_prev_length && sq_displacement < sq_next_length; if (can_displace) { // displacement to apply to the vertices to match @@ -1644,9 +1644,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) const MultiVertexBuffer& v_multibuffer = vertices[i]; for (const VertexBuffer& v_buffer : v_multibuffer) { - size_t size_elements = v_buffer.size(); - size_t size_bytes = size_elements * sizeof(float); - size_t vertices_count = size_elements / t_buffer.vertices.vertex_size_floats(); + const size_t size_elements = v_buffer.size(); + const size_t size_bytes = size_elements * sizeof(float); + const size_t vertices_count = size_elements / t_buffer.vertices.vertex_size_floats(); t_buffer.vertices.count += vertices_count; #if ENABLE_GCODE_VIEWER_STATISTICS @@ -1709,7 +1709,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) progress_count = 0; } - unsigned char id = buffer_id(curr.type); + const unsigned char id = buffer_id(curr.type); TBuffer& t_buffer = m_buffers[id]; MultiIndexBuffer& i_multibuffer = indices[id]; CurrVertexBuffer& curr_vertex_buffer = curr_vertex_buffers[id]; @@ -1779,8 +1779,8 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) TBuffer& t_buffer = m_buffers[i]; const MultiIndexBuffer& i_multibuffer = indices[i]; for (const IndexBuffer& i_buffer : i_multibuffer) { - size_t size_elements = i_buffer.size(); - size_t size_bytes = size_elements * sizeof(IBufferType); + const size_t size_elements = i_buffer.size(); + const size_t size_bytes = size_elements * sizeof(IBufferType); // stores index buffer informations into TBuffer t_buffer.indices.push_back(IBuffer()); @@ -1844,7 +1844,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) if (move.type == EMoveType::Extrude) { // layers zs const double* const last_z = m_layers.empty() ? nullptr : &m_layers.get_zs().back(); - double z = static_cast(move.position[2]); + const double z = static_cast(move.position.z()); if (last_z == nullptr || z < *last_z - EPSILON || *last_z + EPSILON < z) m_layers.append(z, { last_travel_s_id, i }); else @@ -1881,7 +1881,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) if (!options_zs.empty()) { TBuffer& extrude_buffer = m_buffers[buffer_id(EMoveType::Extrude)]; for (Path& path : extrude_buffer.paths) { - float z = path.sub_paths.front().first.position[2]; + const float z = path.sub_paths.front().first.position.z(); if (std::find_if(options_zs.begin(), options_zs.end(), [z](float f) { return f - EPSILON <= z && z <= f + EPSILON; }) != options_zs.end()) path.cp_color_id = 255 - path.cp_color_id; } @@ -1918,12 +1918,12 @@ void GCodeViewer::load_shells(const Print& print, bool initialized) if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptFFF) { // adds wipe tower's volume - double max_z = print.objects()[0]->model_object()->get_model()->bounding_box().max(2); + const double max_z = print.objects()[0]->model_object()->get_model()->bounding_box().max(2); const PrintConfig& config = print.config(); - size_t extruders_count = config.nozzle_diameter.size(); + const size_t extruders_count = config.nozzle_diameter.size(); if ((extruders_count > 1) && config.wipe_tower && !config.complete_objects) { - float depth = print.wipe_tower_data(extruders_count).depth; - float brim_width = print.wipe_tower_data(extruders_count).brim_width; + const float depth = print.wipe_tower_data(extruders_count).depth; + const float brim_width = print.wipe_tower_data(extruders_count).brim_width; m_shells.volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_rotation_angle, !print.is_step_done(psWipeTower), brim_width, initialized); @@ -2427,7 +2427,7 @@ void GCodeViewer::render_toolpaths() #else auto render_as_triangles = [] #endif // ENABLE_GCODE_VIEWER_STATISTICS -(const TBuffer& buffer, unsigned int ibuffer_id, GLShaderProgram& shader) { + (const TBuffer& buffer, unsigned int ibuffer_id, GLShaderProgram& shader) { for (const RenderPath& path : buffer.render_paths) { if (path.ibuffer_id == ibuffer_id) { shader.set_uniform("uniform_color", path.color); From c4ec355f41b705d7313b7d2bfd9f94850ff1bf1f Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 4 Aug 2021 13:58:44 +0200 Subject: [PATCH 05/60] Added function to generated diamond shaped model --- src/slic3r/GUI/GLModel.cpp | 48 ++++++++++++++++++++++++++++++++++++++ src/slic3r/GUI/GLModel.hpp | 5 ++++ 2 files changed, 53 insertions(+) diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index 6d54ec20e..c4437a87f 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -597,5 +597,53 @@ GLModel::InitializationData straight_arrow(float tip_width, float tip_height, fl return data; } +GLModel::InitializationData diamond(int resolution) +{ + resolution = std::max(4, resolution); + + GLModel::InitializationData data; + GLModel::InitializationData::Entity entity; + entity.type = GLModel::PrimitiveType::Triangles; + + const float step = 2.0f * float(PI) / float(resolution); + + // positions + for (int i = 0; i < resolution; ++i) { + float ii = float(i) * step; + entity.positions.emplace_back(0.5f * ::cos(ii), 0.5f * ::sin(ii), 0.0f); + } + entity.positions.emplace_back(0.0f, 0.0f, 0.5f); + entity.positions.emplace_back(0.0f, 0.0f, -0.5f); + + // normals + for (const Vec3f& v : entity.positions) { + entity.normals.emplace_back(v.normalized()); + } + + // triangles + // top + for (int i = 0; i < resolution; ++i) { + entity.indices.push_back(i + 0); + entity.indices.push_back(i + 1); + entity.indices.push_back(resolution); + } + entity.indices.push_back(resolution - 1); + entity.indices.push_back(0); + entity.indices.push_back(resolution); + + // bottom + for (int i = 0; i < resolution; ++i) { + entity.indices.push_back(i + 0); + entity.indices.push_back(resolution + 1); + entity.indices.push_back(i + 1); + } + entity.indices.push_back(resolution - 1); + entity.indices.push_back(resolution + 1); + entity.indices.push_back(0); + + data.entities.emplace_back(entity); + return data; +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index cab2fe220..99c4bf442 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -100,6 +100,11 @@ namespace GUI { // used to render sidebar hints for position and scale GLModel::InitializationData straight_arrow(float tip_width, float tip_height, float stem_width, float stem_height, float thickness); + // create a diamond with the given resolution + // the origin of the diamond is in its center + // the diamond is contained into a box with size [1, 1, 1] + GLModel::InitializationData diamond(int resolution); + } // namespace GUI } // namespace Slic3r From 55bac686031fa366f452111d84b5b58c2dd22a10 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 4 Aug 2021 15:13:43 +0200 Subject: [PATCH 06/60] Tech ENABLE_SEAMS_USING_MODELS - 1st installment --- src/libslic3r/Technologies.hpp | 2 + src/slic3r/GUI/GCodeViewer.cpp | 437 ++++++++++++++++++++++----------- src/slic3r/GUI/GCodeViewer.hpp | 65 ++++- 3 files changed, 361 insertions(+), 143 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index f6366c18e..768b0cb6a 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -47,6 +47,8 @@ #define ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER (1 && ENABLE_2_4_0_ALPHA0) // Enable drawing contours, at cut level, for sinking volumes #define ENABLE_SINKING_CONTOURS (1 && ENABLE_2_4_0_ALPHA0) +// Enable rendering seams (and other options) in preview using models +#define ENABLE_SEAMS_USING_MODELS (1 && ENABLE_2_4_0_ALPHA0) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index c5109f07e..418d00972 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -136,18 +136,26 @@ bool GCodeViewer::Path::matches(const GCodeProcessor::MoveVertex& move) const } } +#if ENABLE_SEAMS_USING_MODELS +void GCodeViewer::TBuffer::Model::reset() +{ + instances.clear(); +} +#endif // ENABLE_SEAMS_USING_MODELS + void GCodeViewer::TBuffer::reset() { - // release gpu memory vertices.reset(); for (IBuffer& buffer : indices) { buffer.reset(); } - // release cpu memory indices.clear(); paths.clear(); render_paths.clear(); +#if ENABLE_SEAMS_USING_MODELS + model.reset(); +#endif // ENABLE_SEAMS_USING_MODELS } void GCodeViewer::TBuffer::add_path(const GCodeProcessor::MoveVertex& move, unsigned int b_id, size_t i_id, size_t s_id) @@ -544,6 +552,18 @@ GCodeViewer::GCodeViewer() switch (buffer_type(i)) { default: { break; } +#if ENABLE_SEAMS_USING_MODELS + case EMoveType::Tool_change: + case EMoveType::Color_change: + case EMoveType::Pause_Print: + case EMoveType::Custom_GCode: + case EMoveType::Retract: + case EMoveType::Unretract: + case EMoveType::Seam: { + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Model; + break; + } +#else case EMoveType::Tool_change: case EMoveType::Color_change: case EMoveType::Pause_Print: @@ -555,6 +575,7 @@ GCodeViewer::GCodeViewer() buffer.vertices.format = VBuffer::EFormat::Position; break; } +#endif // ENABLE_SEAMS_USING_MODELS case EMoveType::Wipe: case EMoveType::Extrude: { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Triangle; @@ -611,7 +632,7 @@ void GCodeViewer::load(const GCodeProcessor::Result& gcode_result, const Print& if (!gcode_result.bed_shape.empty()) { // bed shape detected in the gcode bed_shape = gcode_result.bed_shape; - auto bundle = wxGetApp().preset_bundle; + const auto bundle = wxGetApp().preset_bundle; if (bundle != nullptr && !m_settings_ids.printer.empty()) { const Preset* preset = bundle->printers.find_preset(m_settings_ids.printer); if (preset != nullptr) { @@ -623,10 +644,10 @@ void GCodeViewer::load(const GCodeProcessor::Result& gcode_result, const Print& else { // adjust printbed size in dependence of toolpaths bbox const double margin = 10.0; - Vec2d min(m_paths_bounding_box.min.x() - margin, m_paths_bounding_box.min.y() - margin); - Vec2d max(m_paths_bounding_box.max.x() + margin, m_paths_bounding_box.max.y() + margin); + const Vec2d min(m_paths_bounding_box.min.x() - margin, m_paths_bounding_box.min.y() - margin); + const Vec2d max(m_paths_bounding_box.max.x() + margin, m_paths_bounding_box.max.y() + margin); - Vec2d size = max - min; + const Vec2d size = max - min; bed_shape = { { min.x(), min.y() }, { max.x(), min.y() }, @@ -648,7 +669,7 @@ void GCodeViewer::load(const GCodeProcessor::Result& gcode_result, const Print& m_print_statistics = gcode_result.print_statistics; if (m_time_estimate_mode != PrintEstimatedStatistics::ETimeMode::Normal) { - float time = m_print_statistics.modes[static_cast(m_time_estimate_mode)].time; + const float time = m_print_statistics.modes[static_cast(m_time_estimate_mode)].time; if (time == 0.0f || short_time(get_time_dhms(time)) == short_time(get_time_dhms(m_print_statistics.modes[static_cast(PrintEstimatedStatistics::ETimeMode::Normal)].time))) m_time_estimate_mode = PrintEstimatedStatistics::ETimeMode::Normal; @@ -764,7 +785,8 @@ void GCodeViewer::render() // initializes opengl data of TBuffers for (size_t i = 0; i < m_buffers.size(); ++i) { TBuffer& buffer = m_buffers[i]; - switch (buffer_type(i)) + EMoveType type = buffer_type(i); + switch (type) { default: { break; } case EMoveType::Tool_change: @@ -774,8 +796,15 @@ void GCodeViewer::render() case EMoveType::Retract: case EMoveType::Unretract: case EMoveType::Seam: { +#if ENABLE_SEAMS_USING_MODELS + buffer.shader = "gouraud_light"; + buffer.model.model.init_from(diamond(16)); + buffer.model.color = option_color(type); + break; +#else buffer.shader = wxGetApp().is_glsl_version_greater_or_equal_to(1, 20) ? "options_120" : "options_110"; break; +#endif // ENABLE_SEAMS_USING_MODELS } case EMoveType::Wipe: case EMoveType::Extrude: { @@ -844,8 +873,8 @@ void GCodeViewer::update_sequential_view_current(unsigned int first, unsigned in return false; }; - int first_diff = static_cast(first) - static_cast(m_sequential_view.last_current.first); - int last_diff = static_cast(last) - static_cast(m_sequential_view.last_current.last); + const int first_diff = static_cast(first) - static_cast(m_sequential_view.last_current.first); + const int last_diff = static_cast(last) - static_cast(m_sequential_view.last_current.last); unsigned int new_first = first; unsigned int new_last = last; @@ -1371,6 +1400,18 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) sq_prev_length = sq_length; }; +#if ENABLE_SEAMS_USING_MODELS + // format data into the buffers to be rendered as model + auto add_model_instance = [](const GCodeProcessor::MoveVertex& curr, TBuffer::Model::Instances& instances, size_t move_id) { + TBuffer::Model::Instance instance; + instance.position = curr.position; + instance.width = 1.2f * curr.width; + instance.height = 1.2f * curr.height; + instance.s_id = move_id; + instances.emplace_back(instance); + }; +#endif // ENABLE_SEAMS_USING_MODELS + #if ENABLE_GCODE_VIEWER_STATISTICS auto start_time = std::chrono::high_resolution_clock::now(); m_statistics.results_size = SLIC3R_STDVEC_MEMSIZE(gcode_result.moves, GCodeProcessor::MoveVertex); @@ -1460,6 +1501,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) case TBuffer::ERenderPrimitiveType::Point: { add_vertices_as_point(curr, v_buffer); break; } case TBuffer::ERenderPrimitiveType::Line: { add_vertices_as_line(prev, curr, v_buffer); break; } case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast(v_multibuffer.size()) - 1, v_buffer, i); break; } +#if ENABLE_SEAMS_USING_MODELS + case TBuffer::ERenderPrimitiveType::Model: { add_model_instance(curr, t_buffer.model.instances, i); break; } +#endif // ENABLE_SEAMS_USING_MODELS } // collect options zs for later use @@ -1641,28 +1685,34 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // send vertices data to gpu for (size_t i = 0; i < m_buffers.size(); ++i) { TBuffer& t_buffer = m_buffers[i]; - - const MultiVertexBuffer& v_multibuffer = vertices[i]; - for (const VertexBuffer& v_buffer : v_multibuffer) { - const size_t size_elements = v_buffer.size(); - const size_t size_bytes = size_elements * sizeof(float); - const size_t vertices_count = size_elements / t_buffer.vertices.vertex_size_floats(); - t_buffer.vertices.count += vertices_count; +#if ENABLE_SEAMS_USING_MODELS + if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) { +#endif // ENABLE_SEAMS_USING_MODELS + const MultiVertexBuffer& v_multibuffer = vertices[i]; + for (const VertexBuffer& v_buffer : v_multibuffer) { + const size_t size_elements = v_buffer.size(); + const size_t size_bytes = size_elements * sizeof(float); + const size_t vertices_count = size_elements / t_buffer.vertices.vertex_size_floats(); + t_buffer.vertices.count += vertices_count; #if ENABLE_GCODE_VIEWER_STATISTICS - m_statistics.total_vertices_gpu_size += static_cast(size_bytes); - m_statistics.max_vbuffer_gpu_size = std::max(m_statistics.max_vbuffer_gpu_size, static_cast(size_bytes)); - ++m_statistics.vbuffers_count; + m_statistics.total_vertices_gpu_size += static_cast(size_bytes); + m_statistics.max_vbuffer_gpu_size = std::max(m_statistics.max_vbuffer_gpu_size, static_cast(size_bytes)); + ++m_statistics.vbuffers_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS - GLuint id = 0; - glsafe(::glGenBuffers(1, &id)); - t_buffer.vertices.vbos.push_back(static_cast(id)); - t_buffer.vertices.sizes.push_back(size_bytes); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, id)); - glsafe(::glBufferData(GL_ARRAY_BUFFER, size_bytes, v_buffer.data(), GL_STATIC_DRAW)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + GLuint id = 0; + glsafe(::glGenBuffers(1, &id)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, id)); + glsafe(::glBufferData(GL_ARRAY_BUFFER, size_bytes, v_buffer.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + + t_buffer.vertices.vbos.push_back(static_cast(id)); + t_buffer.vertices.sizes.push_back(size_bytes); + } +#if ENABLE_SEAMS_USING_MODELS } +#endif // ENABLE_SEAMS_USING_MODELS } #if ENABLE_GCODE_VIEWER_STATISTICS @@ -1718,7 +1768,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // ensure there is at least one index buffer if (i_multibuffer.empty()) { i_multibuffer.push_back(IndexBuffer()); - vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); +#if ENABLE_SEAMS_USING_MODELS + if (!t_buffer.vertices.vbos.empty()) +#endif // ENABLE_SEAMS_USING_MODELS + vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); } // if adding the indices for the current segment exceeds the threshold size of the current index buffer @@ -1777,28 +1830,34 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // toolpaths data -> send indices data to gpu for (size_t i = 0; i < m_buffers.size(); ++i) { TBuffer& t_buffer = m_buffers[i]; - const MultiIndexBuffer& i_multibuffer = indices[i]; - for (const IndexBuffer& i_buffer : i_multibuffer) { - const size_t size_elements = i_buffer.size(); - const size_t size_bytes = size_elements * sizeof(IBufferType); +#if ENABLE_SEAMS_USING_MODELS + if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) { +#endif // ENABLE_SEAMS_USING_MODELS + const MultiIndexBuffer& i_multibuffer = indices[i]; + for (const IndexBuffer& i_buffer : i_multibuffer) { + const size_t size_elements = i_buffer.size(); + const size_t size_bytes = size_elements * sizeof(IBufferType); - // stores index buffer informations into TBuffer - t_buffer.indices.push_back(IBuffer()); - IBuffer& ibuf = t_buffer.indices.back(); - ibuf.count = size_elements; - ibuf.vbo = vbo_indices[i][t_buffer.indices.size() - 1]; + // stores index buffer informations into TBuffer + t_buffer.indices.push_back(IBuffer()); + IBuffer& ibuf = t_buffer.indices.back(); + ibuf.count = size_elements; + ibuf.vbo = vbo_indices[i][t_buffer.indices.size() - 1]; #if ENABLE_GCODE_VIEWER_STATISTICS - m_statistics.total_indices_gpu_size += static_cast(size_bytes); - m_statistics.max_ibuffer_gpu_size = std::max(m_statistics.max_ibuffer_gpu_size, static_cast(size_bytes)); - ++m_statistics.ibuffers_count; + m_statistics.total_indices_gpu_size += static_cast(size_bytes); + m_statistics.max_ibuffer_gpu_size = std::max(m_statistics.max_ibuffer_gpu_size, static_cast(size_bytes)); + ++m_statistics.ibuffers_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS - glsafe(::glGenBuffers(1, &ibuf.ibo)); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf.ibo)); - glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, size_bytes, i_buffer.data(), GL_STATIC_DRAW)); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + glsafe(::glGenBuffers(1, &ibuf.ibo)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuf.ibo)); + glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, size_bytes, i_buffer.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + } +#if ENABLE_SEAMS_USING_MODELS } +#endif // ENABLE_SEAMS_USING_MODELS } if (progress_dialog != nullptr) { @@ -1921,7 +1980,7 @@ void GCodeViewer::load_shells(const Print& print, bool initialized) const double max_z = print.objects()[0]->model_object()->get_model()->bounding_box().max(2); const PrintConfig& config = print.config(); const size_t extruders_count = config.nozzle_diameter.size(); - if ((extruders_count > 1) && config.wipe_tower && !config.complete_objects) { + if (extruders_count > 1 && config.wipe_tower && !config.complete_objects) { const float depth = print.wipe_tower_data(extruders_count).depth; const float brim_width = print.wipe_tower_data(extruders_count).brim_width; @@ -2014,8 +2073,8 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool path.sub_paths.back().last = buffer.paths[last].sub_paths.back().last; } - size_t min_s_id = m_layers.get_endpoints_at(min_id).first; - size_t max_s_id = m_layers.get_endpoints_at(max_id).last; + const size_t min_s_id = m_layers.get_endpoints_at(min_id).first; + const size_t max_s_id = m_layers.get_endpoints_at(max_id).last; return (min_s_id <= path.sub_paths.front().first.s_id && path.sub_paths.front().first.s_id <= max_s_id) || (min_s_id <= path.sub_paths.back().last.s_id && path.sub_paths.back().last.s_id <= max_s_id); @@ -2026,7 +2085,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool statistics->render_paths_size = 0; #endif // ENABLE_GCODE_VIEWER_STATISTICS - bool top_layer_only = get_app_config()->get("seq_top_layer_only") == "1"; + const bool top_layer_only = get_app_config()->get("seq_top_layer_only") == "1"; SequentialView::Endpoints global_endpoints = { m_moves_count , 0 }; SequentialView::Endpoints top_layer_endpoints = global_endpoints; @@ -2044,39 +2103,62 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool if (!buffer.visible) continue; - for (size_t i = 0; i < buffer.paths.size(); ++i) { - const Path& path = buffer.paths[i]; - if (path.type == EMoveType::Travel) { - if (!is_travel_in_layers_range(i, m_layers_z_range[0], m_layers_z_range[1])) +#if ENABLE_SEAMS_USING_MODELS + if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { + for (const TBuffer::Model::Instance& inst : buffer.model.instances) { + if (inst.s_id < m_layers.get_endpoints_at(m_layers_z_range[0]).first || m_layers.get_endpoints_at(m_layers_z_range[1]).last < inst.s_id) continue; + + global_endpoints.first = std::min(global_endpoints.first, inst.s_id); + global_endpoints.last = std::max(global_endpoints.last, inst.s_id); + + if (top_layer_only) { + if (inst.s_id < m_layers.get_endpoints_at(m_layers_z_range[1]).first || m_layers.get_endpoints_at(m_layers_z_range[1]).last < inst.s_id) + continue; + + top_layer_endpoints.first = std::min(top_layer_endpoints.first, inst.s_id); + top_layer_endpoints.last = std::max(top_layer_endpoints.last, inst.s_id); + } } - else if (!is_in_layers_range(path, m_layers_z_range[0], m_layers_z_range[1])) - continue; - - if (path.type == EMoveType::Extrude && !is_visible(path)) - continue; - - // store valid path - for (size_t j = 0; j < path.sub_paths.size(); ++j) { - paths.push_back({ static_cast(b), path.sub_paths[j].first.b_id, static_cast(i), static_cast(j) }); - } - - global_endpoints.first = std::min(global_endpoints.first, path.sub_paths.front().first.s_id); - global_endpoints.last = std::max(global_endpoints.last, path.sub_paths.back().last.s_id); - - if (top_layer_only) { + } + else { +#endif // ENABLE_SEAMS_USING_MODELS + for (size_t i = 0; i < buffer.paths.size(); ++i) { + const Path& path = buffer.paths[i]; if (path.type == EMoveType::Travel) { - if (is_travel_in_layers_range(i, m_layers_z_range[1], m_layers_z_range[1])) { + if (!is_travel_in_layers_range(i, m_layers_z_range[0], m_layers_z_range[1])) + continue; + } + else if (!is_in_layers_range(path, m_layers_z_range[0], m_layers_z_range[1])) + continue; + + if (path.type == EMoveType::Extrude && !is_visible(path)) + continue; + + // store valid path + for (size_t j = 0; j < path.sub_paths.size(); ++j) { + paths.push_back({ static_cast(b), path.sub_paths[j].first.b_id, static_cast(i), static_cast(j) }); + } + + global_endpoints.first = std::min(global_endpoints.first, path.sub_paths.front().first.s_id); + global_endpoints.last = std::max(global_endpoints.last, path.sub_paths.back().last.s_id); + + if (top_layer_only) { + if (path.type == EMoveType::Travel) { + if (is_travel_in_layers_range(i, m_layers_z_range[1], m_layers_z_range[1])) { + top_layer_endpoints.first = std::min(top_layer_endpoints.first, path.sub_paths.front().first.s_id); + top_layer_endpoints.last = std::max(top_layer_endpoints.last, path.sub_paths.back().last.s_id); + } + } + else if (is_in_layers_range(path, m_layers_z_range[1], m_layers_z_range[1])) { top_layer_endpoints.first = std::min(top_layer_endpoints.first, path.sub_paths.front().first.s_id); top_layer_endpoints.last = std::max(top_layer_endpoints.last, path.sub_paths.back().last.s_id); } } - else if (is_in_layers_range(path, m_layers_z_range[1], m_layers_z_range[1])) { - top_layer_endpoints.first = std::min(top_layer_endpoints.first, path.sub_paths.front().first.s_id); - top_layer_endpoints.last = std::max(top_layer_endpoints.last, path.sub_paths.back().last.s_id); - } } +#if ENABLE_SEAMS_USING_MODELS } +#endif // ENABLE_SEAMS_USING_MODELS } // update current sequential position @@ -2086,42 +2168,57 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool // get the world position from gpu bool found = false; for (const TBuffer& buffer : m_buffers) { - // searches the path containing the current position - for (const Path& path : buffer.paths) { - if (path.contains(m_sequential_view.current.last)) { - int sub_path_id = path.get_id_of_sub_path_containing(m_sequential_view.current.last); - if (sub_path_id != -1) { - const Path::Sub_Path& sub_path = path.sub_paths[sub_path_id]; - unsigned int offset = static_cast(m_sequential_view.current.last - sub_path.first.s_id); - if (offset > 0) { - if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Line) - offset = 2 * offset - 1; - else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) { - unsigned int indices_count = buffer.indices_per_segment(); - offset = indices_count * (offset - 1) + (indices_count - 2); - if (sub_path_id == 0) - offset += 6; // add 2 triangles for starting cap - } - } - offset += static_cast(sub_path.first.i_id); - - // gets the vertex index from the index buffer on gpu - const IBuffer& i_buffer = buffer.indices[sub_path.first.b_id]; - unsigned int index = 0; - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); - glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast(offset * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&index))); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - - // gets the position from the vertices buffer on gpu - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); - glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(index * buffer.vertices.vertex_size_bytes()), static_cast(3 * sizeof(float)), static_cast(sequential_view->current_position.data()))); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); - +#if ENABLE_SEAMS_USING_MODELS + if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { + for (const TBuffer::Model::Instance& inst : buffer.model.instances) { + if (inst.s_id == m_sequential_view.current.last) { + sequential_view->current_position = inst.position; found = true; break; } } } + else { +#endif // ENABLE_SEAMS_USING_MODELS + // searches the path containing the current position + for (const Path& path : buffer.paths) { + if (path.contains(m_sequential_view.current.last)) { + const int sub_path_id = path.get_id_of_sub_path_containing(m_sequential_view.current.last); + if (sub_path_id != -1) { + const Path::Sub_Path& sub_path = path.sub_paths[sub_path_id]; + unsigned int offset = static_cast(m_sequential_view.current.last - sub_path.first.s_id); + if (offset > 0) { + if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Line) + offset = 2 * offset - 1; + else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) { + unsigned int indices_count = buffer.indices_per_segment(); + offset = indices_count * (offset - 1) + (indices_count - 2); + if (sub_path_id == 0) + offset += 6; // add 2 triangles for starting cap + } + } + offset += static_cast(sub_path.first.i_id); + + // gets the vertex index from the index buffer on gpu + const IBuffer& i_buffer = buffer.indices[sub_path.first.b_id]; + unsigned int index = 0; + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); + glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast(offset * sizeof(IBufferType)), static_cast(sizeof(IBufferType)), static_cast(&index))); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + + // gets the position from the vertices buffer on gpu + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); + glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(index * buffer.vertices.vertex_size_bytes()), static_cast(3 * sizeof(float)), static_cast(sequential_view->current_position.data()))); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + + found = true; + break; + } + } + } +#if ENABLE_SEAMS_USING_MODELS + } +#endif // ENABLE_SEAMS_USING_MODELS if (found) break; @@ -2230,6 +2327,9 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool // set sequential data to their final value sequential_view->endpoints = top_layer_only ? top_layer_endpoints : global_endpoints; sequential_view->current.first = !top_layer_only && keep_sequential_current_first ? std::clamp(sequential_view->current.first, sequential_view->endpoints.first, sequential_view->endpoints.last) : sequential_view->endpoints.first; +#if ENABLE_SEAMS_USING_MODELS + sequential_view->global = global_endpoints; +#endif // ENABLE_SEAMS_USING_MODELS // updates sequential range caps std::array* sequential_range_caps = const_cast*>(&m_sequential_range_caps); @@ -2351,6 +2451,9 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool statistics->render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.sizes, unsigned int); statistics->render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.offsets, size_t); } +#if ENABLE_SEAMS_USING_MODELS + statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances, TBuffer::Model::Instance); +#endif // ENABLE_SEAMS_USING_MODELS } statistics->refresh_paths_time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -2439,17 +2542,49 @@ void GCodeViewer::render_toolpaths() } }; +#if ENABLE_SEAMS_USING_MODELS +#if ENABLE_GCODE_VIEWER_STATISTICS + auto render_as_instanced_model = [this] +#else + auto render_as_instanced_model = [] +#endif // ENABLE_GCODE_VIEWER_STATISTICS + (TBuffer & buffer, GLShaderProgram & shader) { + for (const TBuffer::Model::Instance& inst : buffer.model.instances) { + bool top_layer_only = get_app_config()->get("seq_top_layer_only") == "1"; + bool visible = top_layer_only ? + m_sequential_view.global.first <= inst.s_id && inst.s_id <= m_sequential_view.global.last : + m_sequential_view.current.first <= inst.s_id && inst.s_id <= m_sequential_view.current.last; + + if (visible) { + glsafe(::glPushMatrix()); + glsafe(::glTranslatef(inst.position.x(), inst.position.y(), inst.position.z() - 0.5f * inst.height)); + glsafe(::glScalef(inst.width, inst.width, inst.height)); + Color color = (top_layer_only && m_sequential_view.current.last != m_sequential_view.global.last && inst.s_id < m_sequential_view.endpoints.first) ? + Neutral_Color : buffer.model.color; + buffer.model.model.set_color(-1, color); + buffer.model.model.render(); + glsafe(::glPopMatrix()); +#if ENABLE_GCODE_VIEWER_STATISTICS + ++m_statistics.gl_models_calls_count; +#endif // ENABLE_GCODE_VIEWER_STATISTICS + } + } + }; +#endif // ENABLE_SEAMS_USING_MODELS + auto line_width = [](double zoom) { return (zoom < 5.0) ? 1.0 : (1.0 + 5.0 * (zoom - 5.0) / (100.0 - 5.0)); }; - glsafe(::glLineWidth(static_cast(line_width(zoom)))); - unsigned char begin_id = buffer_id(EMoveType::Retract); unsigned char end_id = buffer_id(EMoveType::Count); for (unsigned char i = begin_id; i < end_id; ++i) { +#if ENABLE_SEAMS_USING_MODELS + TBuffer& buffer = m_buffers[i]; +#else const TBuffer& buffer = m_buffers[i]; +#endif // ENABLE_SEAMS_USING_MODELS if (!buffer.visible || !buffer.has_data()) continue; @@ -2457,44 +2592,56 @@ void GCodeViewer::render_toolpaths() if (shader != nullptr) { shader->start_using(); - for (size_t j = 0; j < buffer.indices.size(); ++j) { - const IBuffer& i_buffer = buffer.indices[j]; - - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); - glsafe(::glVertexPointer(buffer.vertices.position_size_floats(), GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); - glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); - bool has_normals = buffer.vertices.normal_size_floats() > 0; - if (has_normals) { - glsafe(::glNormalPointer(GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); - glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); - } - - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); - - switch (buffer.render_primitive_type) - { - case TBuffer::ERenderPrimitiveType::Point: { - render_as_points(buffer, static_cast(j), *shader); - break; - } - case TBuffer::ERenderPrimitiveType::Line: { - render_as_lines(buffer, static_cast(j), *shader); - break; - } - case TBuffer::ERenderPrimitiveType::Triangle: { - render_as_triangles(buffer, static_cast(j), *shader); - break; - } - } - - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); - - if (has_normals) - glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); - - glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); +#if ENABLE_SEAMS_USING_MODELS + if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { + shader->set_uniform("emission_factor", 0.25f); + render_as_instanced_model(buffer, *shader); + shader->set_uniform("emission_factor", 0.0f); } + else { +#endif // ENABLE_SEAMS_USING_MODELS + for (size_t j = 0; j < buffer.indices.size(); ++j) { + const IBuffer& i_buffer = buffer.indices[j]; + + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo)); + glsafe(::glVertexPointer(buffer.vertices.position_size_floats(), GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.position_offset_bytes())); + glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); + bool has_normals = buffer.vertices.normal_size_floats() > 0; + if (has_normals) { + glsafe(::glNormalPointer(GL_FLOAT, buffer.vertices.vertex_size_bytes(), (const void*)buffer.vertices.normal_offset_bytes())); + glsafe(::glEnableClientState(GL_NORMAL_ARRAY)); + } + + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo)); + + switch (buffer.render_primitive_type) + { + case TBuffer::ERenderPrimitiveType::Point: { + render_as_points(buffer, static_cast(j), *shader); + break; + } + case TBuffer::ERenderPrimitiveType::Line: { + glsafe(::glLineWidth(static_cast(line_width(zoom)))); + render_as_lines(buffer, static_cast(j), *shader); + break; + } + case TBuffer::ERenderPrimitiveType::Triangle: { + render_as_triangles(buffer, static_cast(j), *shader); + break; + } + } + + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + + if (has_normals) + glsafe(::glDisableClientState(GL_NORMAL_ARRAY)); + + glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + } +#if ENABLE_SEAMS_USING_MODELS + } +#endif // ENABLE_SEAMS_USING_MODELS shader->stop_using(); } @@ -3488,6 +3635,9 @@ void GCodeViewer::render_statistics() add_counter(std::string("Multi GL_LINES:"), m_statistics.gl_multi_lines_calls_count); add_counter(std::string("Multi GL_TRIANGLES:"), m_statistics.gl_multi_triangles_calls_count); add_counter(std::string("GL_TRIANGLES:"), m_statistics.gl_triangles_calls_count); +#if ENABLE_SEAMS_USING_MODELS + add_counter(std::string("Models:"), m_statistics.gl_models_calls_count); +#endif // ENABLE_SEAMS_USING_MODELS } if (ImGui::CollapsingHeader("CPU memory")) { @@ -3496,6 +3646,9 @@ void GCodeViewer::render_statistics() ImGui::Separator(); add_memory(std::string("Paths:"), m_statistics.paths_size); add_memory(std::string("Render paths:"), m_statistics.render_paths_size); +#if ENABLE_SEAMS_USING_MODELS + add_memory(std::string("Models instances:"), m_statistics.models_instances_size); +#endif // ENABLE_SEAMS_USING_MODELS } if (ImGui::CollapsingHeader("GPU memory")) { diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 3d9b9bb69..53bc66def 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -81,7 +81,10 @@ class GCodeViewer size_t position_size_floats() const { return 3; } size_t position_size_bytes() const { return position_size_floats() * sizeof(float); } - size_t normal_offset_floats() const { return position_size_floats(); } + size_t normal_offset_floats() const { + assert(format == EFormat::PositionNormal1 || format == EFormat::PositionNormal3); + return position_size_floats(); + } size_t normal_offset_bytes() const { return normal_offset_floats() * sizeof(float); } size_t normal_size_floats() const { @@ -230,13 +233,43 @@ class GCodeViewer { Point, Line, +#if ENABLE_SEAMS_USING_MODELS + Triangle, + Model +#else Triangle +#endif // ENABLE_SEAMS_USING_MODELS }; ERenderPrimitiveType render_primitive_type; + + // buffers for point, line and triangle primitive types VBuffer vertices; std::vector indices; +#if ENABLE_SEAMS_USING_MODELS + struct Model + { + struct Instance + { + Vec3f position; + float width; + float height; + size_t s_id; + }; + using Instances = std::vector; + + GLModel model; + Color color; + Instances instances; + + void reset(); + }; + + // contain the buffer for model primitive types + Model model; +#endif // ENABLE_SEAMS_USING_MODELS + std::string shader; std::vector paths; // std::set seems to perform significantly better, at least on Windows. @@ -284,9 +317,24 @@ class GCodeViewer } size_t max_indices_per_segment_size_bytes() const { return max_indices_per_segment() * sizeof(IBufferType); } +#if ENABLE_SEAMS_USING_MODELS + bool has_data() const { + switch (render_primitive_type) + { + case ERenderPrimitiveType::Point: + case ERenderPrimitiveType::Line: + case ERenderPrimitiveType::Triangle: { + return !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; + } + case ERenderPrimitiveType::Model: { return model.model.is_initialized() && !model.instances.empty(); } + default: { return false; } + } + } +#else bool has_data() const { return !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; } +#endif // ENABLE_SEAMS_USING_MODELS }; // helper to render shells @@ -434,6 +482,9 @@ class GCodeViewer int64_t gl_multi_lines_calls_count{ 0 }; int64_t gl_multi_triangles_calls_count{ 0 }; int64_t gl_triangles_calls_count{ 0 }; +#if ENABLE_SEAMS_USING_MODELS + int64_t gl_models_calls_count{ 0 }; +#endif // ENABLE_SEAMS_USING_MODELS // memory int64_t results_size{ 0 }; int64_t total_vertices_gpu_size{ 0 }; @@ -442,6 +493,9 @@ class GCodeViewer int64_t max_ibuffer_gpu_size{ 0 }; int64_t paths_size{ 0 }; int64_t render_paths_size{ 0 }; +#if ENABLE_SEAMS_USING_MODELS + int64_t models_instances_size{ 0 }; +#endif // ENABLE_SEAMS_USING_MODELS // other int64_t travel_segments_count{ 0 }; int64_t wipe_segments_count{ 0 }; @@ -471,6 +525,9 @@ class GCodeViewer gl_multi_lines_calls_count = 0; gl_multi_triangles_calls_count = 0; gl_triangles_calls_count = 0; +#if ENABLE_SEAMS_USING_MODELS + gl_models_calls_count = 0; +#endif // ENABLE_SEAMS_USING_MODELS } void reset_sizes() { @@ -481,6 +538,9 @@ class GCodeViewer max_ibuffer_gpu_size = 0; paths_size = 0; render_paths_size = 0; +#if ENABLE_SEAMS_USING_MODELS + models_instances_size = 0; +#endif // ENABLE_SEAMS_USING_MODELS } void reset_others() { @@ -564,6 +624,9 @@ public: Endpoints endpoints; Endpoints current; Endpoints last_current; +#if ENABLE_SEAMS_USING_MODELS + Endpoints global; +#endif // ENABLE_SEAMS_USING_MODELS Vec3f current_position{ Vec3f::Zero() }; Marker marker; GCodeWindow gcode_window; From 1b03eec234089149ec779374e5b5978a0f445a0e Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 4 Aug 2021 15:23:37 +0200 Subject: [PATCH 07/60] Fixed build of tech ENABLE_SEAMS_USING_MODELS when tech ENABLE_GCODE_VIEWER_STATISTICS is disabled --- src/slic3r/GUI/GCodeViewer.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 418d00972..cc25c31d8 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2543,11 +2543,7 @@ void GCodeViewer::render_toolpaths() }; #if ENABLE_SEAMS_USING_MODELS -#if ENABLE_GCODE_VIEWER_STATISTICS auto render_as_instanced_model = [this] -#else - auto render_as_instanced_model = [] -#endif // ENABLE_GCODE_VIEWER_STATISTICS (TBuffer & buffer, GLShaderProgram & shader) { for (const TBuffer::Model::Instance& inst : buffer.model.instances) { bool top_layer_only = get_app_config()->get("seq_top_layer_only") == "1"; From fd81041adb8e637c4b9422a1c97d723a410cb69c Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 5 Aug 2021 08:10:42 +0200 Subject: [PATCH 08/60] Fixed build warnings on non-Windows OS --- src/slic3r/GUI/GCodeViewer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index cc25c31d8..87e24c957 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1818,6 +1818,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) add_indices_as_solid(prev, curr, next, t_buffer, curr_vertex_buffer.second, static_cast(i_multibuffer.size()) - 1, i_buffer, i); break; } + default: { break; } } } @@ -2286,6 +2287,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool size_in_indices = buffer.indices_per_segment() * segments_count; break; } + default: { break; } } if (size_in_indices == 0) @@ -2625,6 +2627,7 @@ void GCodeViewer::render_toolpaths() render_as_triangles(buffer, static_cast(j), *shader); break; } + default: { break; } } glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); From 8c4e203e1d90b0003fe584edb522c1ae12048120 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 5 Aug 2021 09:09:07 +0200 Subject: [PATCH 09/60] Tech ENABLE_SEAMS_USING_MODELS -> Use new options visualization only if OpenGL 3.1 or greater is detected --- src/slic3r/GUI/GCodeViewer.cpp | 44 +++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 87e24c957..42c34b59b 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -545,6 +545,7 @@ const GCodeViewer::Color GCodeViewer::Neutral_Color = { 0.25f, 0.25f, 0.25f, 1.0 GCodeViewer::GCodeViewer() { +#if !ENABLE_SEAMS_USING_MODELS // initializes non OpenGL data of TBuffers // OpenGL data are initialized into render().init_gl_data() for (size_t i = 0; i < m_buffers.size(); ++i) { @@ -552,18 +553,6 @@ GCodeViewer::GCodeViewer() switch (buffer_type(i)) { default: { break; } -#if ENABLE_SEAMS_USING_MODELS - case EMoveType::Tool_change: - case EMoveType::Color_change: - case EMoveType::Pause_Print: - case EMoveType::Custom_GCode: - case EMoveType::Retract: - case EMoveType::Unretract: - case EMoveType::Seam: { - buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Model; - break; - } -#else case EMoveType::Tool_change: case EMoveType::Color_change: case EMoveType::Pause_Print: @@ -575,7 +564,6 @@ GCodeViewer::GCodeViewer() buffer.vertices.format = VBuffer::EFormat::Position; break; } -#endif // ENABLE_SEAMS_USING_MODELS case EMoveType::Wipe: case EMoveType::Extrude: { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Triangle; @@ -591,6 +579,8 @@ GCodeViewer::GCodeViewer() } set_toolpath_move_type_visible(EMoveType::Extrude, true); +#endif // !ENABLE_SEAMS_USING_MODELS + // m_sequential_view.skip_invisible_moves = true; } @@ -797,25 +787,47 @@ void GCodeViewer::render() case EMoveType::Unretract: case EMoveType::Seam: { #if ENABLE_SEAMS_USING_MODELS - buffer.shader = "gouraud_light"; - buffer.model.model.init_from(diamond(16)); - buffer.model.color = option_color(type); + if (wxGetApp().is_gl_version_greater_or_equal_to(3, 1)) { + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Model; + buffer.shader = "gouraud_light"; + buffer.model.model.init_from(diamond(16)); + buffer.model.color = option_color(type); + } + else { + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Point; + buffer.vertices.format = VBuffer::EFormat::Position; + buffer.shader = wxGetApp().is_glsl_version_greater_or_equal_to(1, 20) ? "options_120" : "options_110"; + } break; #else + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Point; + buffer.vertices.format = VBuffer::EFormat::Position; buffer.shader = wxGetApp().is_glsl_version_greater_or_equal_to(1, 20) ? "options_120" : "options_110"; break; #endif // ENABLE_SEAMS_USING_MODELS } case EMoveType::Wipe: case EMoveType::Extrude: { +#if ENABLE_SEAMS_USING_MODELS + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Triangle; + buffer.vertices.format = VBuffer::EFormat::PositionNormal3; +#endif // ENABLE_SEAMS_USING_MODELS buffer.shader = "gouraud_light"; break; } case EMoveType::Travel: { +#if ENABLE_SEAMS_USING_MODELS + buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Line; + buffer.vertices.format = VBuffer::EFormat::PositionNormal1; +#endif // ENABLE_SEAMS_USING_MODELS buffer.shader = "toolpaths_lines"; break; } } + +#if ENABLE_SEAMS_USING_MODELS + set_toolpath_move_type_visible(EMoveType::Extrude, true); +#endif // ENABLE_SEAMS_USING_MODELS } // initializes tool marker From 73464c76b9cb36f81e1710e9b0a4404094e1ee38 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 5 Aug 2021 09:35:12 +0200 Subject: [PATCH 10/60] Techs ENABLE_SEAMS_USING_MODELS + ENABLE_GCODE_VIEWER_STATISTICS -> Fixed detection of used memory to store instances data --- src/slic3r/GUI/GCodeViewer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 42c34b59b..860d693cc 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2096,6 +2096,9 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool #if ENABLE_GCODE_VIEWER_STATISTICS Statistics* statistics = const_cast(&m_statistics); statistics->render_paths_size = 0; +#if ENABLE_SEAMS_USING_MODELS + statistics->models_instances_size = 0; +#endif // ENABLE_SEAMS_USING_MODELS #endif // ENABLE_GCODE_VIEWER_STATISTICS const bool top_layer_only = get_app_config()->get("seq_top_layer_only") == "1"; From 252935dde74c18c5ee837c4b3a32039105411c24 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 5 Aug 2021 10:19:02 +0200 Subject: [PATCH 11/60] Techs ENABLE_SEAMS_USING_MODELS + ENABLE_GCODE_VIEWER_STATISTICS -> Added instances counter --- src/slic3r/GUI/GCodeViewer.cpp | 21 ++++++++++++++++++++- src/slic3r/GUI/GCodeViewer.hpp | 6 ++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 860d693cc..8730493cb 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1514,7 +1514,14 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) case TBuffer::ERenderPrimitiveType::Line: { add_vertices_as_line(prev, curr, v_buffer); break; } case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast(v_multibuffer.size()) - 1, v_buffer, i); break; } #if ENABLE_SEAMS_USING_MODELS - case TBuffer::ERenderPrimitiveType::Model: { add_model_instance(curr, t_buffer.model.instances, i); break; } + case TBuffer::ERenderPrimitiveType::Model: + { + add_model_instance(curr, t_buffer.model.instances, i); +#if ENABLE_GCODE_VIEWER_STATISTICS + ++m_statistics.instances_count; +#endif // ENABLE_GCODE_VIEWER_STATISTICS + break; + } #endif // ENABLE_SEAMS_USING_MODELS } @@ -1686,6 +1693,15 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) } } +#if ENABLE_SEAMS_USING_MODELS + for (size_t i = 0; i < m_buffers.size(); ++i) { + TBuffer& t_buffer = m_buffers[i]; + if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { + t_buffer.model.instances.shrink_to_fit(); + } + } +#endif // ENABLE_SEAMS_USING_MODELS + // move the wipe toolpaths half height up to render them on proper position MultiVertexBuffer& wipe_vertices = vertices[buffer_id(EMoveType::Wipe)]; for (VertexBuffer& v_buffer : wipe_vertices) { @@ -3677,6 +3693,9 @@ void GCodeViewer::render_statistics() add_counter(std::string("Travel segments count:"), m_statistics.travel_segments_count); add_counter(std::string("Wipe segments count:"), m_statistics.wipe_segments_count); add_counter(std::string("Extrude segments count:"), m_statistics.extrude_segments_count); +#if ENABLE_SEAMS_USING_MODELS + add_counter(std::string("Instances count:"), m_statistics.instances_count); +#endif // ENABLE_SEAMS_USING_MODELS ImGui::Separator(); add_counter(std::string("VBuffers count:"), m_statistics.vbuffers_count); add_counter(std::string("IBuffers count:"), m_statistics.ibuffers_count); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 53bc66def..6103f9722 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -500,6 +500,9 @@ class GCodeViewer int64_t travel_segments_count{ 0 }; int64_t wipe_segments_count{ 0 }; int64_t extrude_segments_count{ 0 }; +#if ENABLE_SEAMS_USING_MODELS + int64_t instances_count{ 0 }; +#endif // ENABLE_SEAMS_USING_MODELS int64_t vbuffers_count{ 0 }; int64_t ibuffers_count{ 0 }; @@ -547,6 +550,9 @@ class GCodeViewer travel_segments_count = 0; wipe_segments_count = 0; extrude_segments_count = 0; +#if ENABLE_SEAMS_USING_MODELS + instances_count = 0; +#endif // ENABLE_SEAMS_USING_MODELS vbuffers_count = 0; ibuffers_count = 0; } From 34da899c66271262f6c9e8c402d7b2c49decca0c Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 5 Aug 2021 15:08:49 +0200 Subject: [PATCH 12/60] Temporary tech ENABLE_SEAMS_USING_INSTANCED_MODELS -> WIP (still missing opengl calls) --- src/libslic3r/Technologies.hpp | 6 ++ src/slic3r/GUI/GCodeViewer.cpp | 140 +++++++++++++++++++++++++++++++++ src/slic3r/GUI/GCodeViewer.hpp | 47 +++++++++++ 3 files changed, 193 insertions(+) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 768b0cb6a..79976d4a0 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -49,6 +49,12 @@ #define ENABLE_SINKING_CONTOURS (1 && ENABLE_2_4_0_ALPHA0) // Enable rendering seams (and other options) in preview using models #define ENABLE_SEAMS_USING_MODELS (1 && ENABLE_2_4_0_ALPHA0) +// Enable rendering seams (and other options) in preview using instanced models +// references: +// https://ogldev.org/www/tutorial33/tutorial33.html +// https://docs.gl/gl3/glDrawElementsInstanced +// https://www.khronos.org/opengl/wiki/Vertex_Rendering#Instancing +#define ENABLE_SEAMS_USING_INSTANCED_MODELS (1 && ENABLE_SEAMS_USING_MODELS) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 8730493cb..b8388f82f 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -95,6 +95,17 @@ void GCodeViewer::VBuffer::reset() count = 0; } +#if ENABLE_SEAMS_USING_INSTANCED_MODELS +void GCodeViewer::InstanceVBuffer::reset() +{ + // release gpu memory + if (vbo > 0) + glsafe(::glDeleteBuffers(1, &vbo)); + s_ids.clear(); + render_range = { 0, 0 }; +} +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS + void GCodeViewer::IBuffer::reset() { // release gpu memory @@ -140,6 +151,9 @@ bool GCodeViewer::Path::matches(const GCodeProcessor::MoveVertex& move) const void GCodeViewer::TBuffer::Model::reset() { instances.clear(); +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + instances2.reset(); +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS } #endif // ENABLE_SEAMS_USING_MODELS @@ -1422,6 +1436,23 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) instance.s_id = move_id; instances.emplace_back(instance); }; + +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + // format data into the buffers to be rendered as model + auto add_model_instance_2 = [](const GCodeProcessor::MoveVertex& curr, InstanceBuffer& instances, InstanceIdBuffer& instances_ids, size_t move_id) { + // append position + instances.push_back(curr.position.x()); + instances.push_back(curr.position.y()); + instances.push_back(curr.position.z()); + // append width + instances.push_back(1.2f * curr.width); + // append height + instances.push_back(1.2f * curr.height); + + // append id + instances_ids.push_back(move_id); + }; +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_SEAMS_USING_MODELS #if ENABLE_GCODE_VIEWER_STATISTICS @@ -1466,6 +1497,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) std::vector vertices(m_buffers.size()); std::vector indices(m_buffers.size()); +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + std::vector instances(m_buffers.size()); + std::vector instances_ids(m_buffers.size()); +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS std::vector options_zs; // toolpaths data -> extract vertices from result @@ -1490,6 +1525,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) const unsigned char id = buffer_id(curr.type); TBuffer& t_buffer = m_buffers[id]; MultiVertexBuffer& v_multibuffer = vertices[id]; +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + InstanceBuffer& inst_buffer = instances[id]; + InstanceIdBuffer& inst_id_buffer = instances_ids[id]; +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS // ensure there is at least one vertex buffer if (v_multibuffer.empty()) @@ -1517,6 +1556,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) case TBuffer::ERenderPrimitiveType::Model: { add_model_instance(curr, t_buffer.model.instances, i); +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + add_model_instance_2(curr, inst_buffer, inst_id_buffer, i); +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.instances_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -1714,7 +1756,31 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) for (size_t i = 0; i < m_buffers.size(); ++i) { TBuffer& t_buffer = m_buffers[i]; #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { + const InstanceBuffer& inst_buffer = instances[i]; + if (!inst_buffer.empty()) { + const size_t size_bytes = inst_buffer.size() * sizeof(float); + +#if ENABLE_GCODE_VIEWER_STATISTICS + m_statistics.total_instances_gpu_size += static_cast(size_bytes); + m_statistics.max_instance_vbuffer_gpu_size = std::max(m_statistics.max_instance_vbuffer_gpu_size, static_cast(size_bytes)); +#endif // ENABLE_GCODE_VIEWER_STATISTICS + + GLuint id = 0; + glsafe(::glGenBuffers(1, &id)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, id)); + glsafe(::glBufferData(GL_ARRAY_BUFFER, size_bytes, inst_buffer.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + + t_buffer.model.instances2.vbo = id; + t_buffer.model.instances2.s_ids = instances_ids[i]; + } + } + else { +#else if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) { +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_SEAMS_USING_MODELS const MultiVertexBuffer& v_multibuffer = vertices[i]; for (const VertexBuffer& v_buffer : v_multibuffer) { @@ -1751,6 +1817,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // dismiss vertices data, no more needed std::vector().swap(vertices); +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + std::vector().swap(instances); + std::vector().swap(instances_ids); +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS // toolpaths data -> extract indices from result // paths may have been filled while extracting vertices, @@ -2137,6 +2207,23 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool #if ENABLE_SEAMS_USING_MODELS if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + for (size_t id : buffer.model.instances2.s_ids) { + if (id < m_layers.get_endpoints_at(m_layers_z_range[0]).first || m_layers.get_endpoints_at(m_layers_z_range[1]).last < id) + continue; + + global_endpoints.first = std::min(global_endpoints.first, id); + global_endpoints.last = std::max(global_endpoints.last, id); + + if (top_layer_only) { + if (id < m_layers.get_endpoints_at(m_layers_z_range[1]).first || m_layers.get_endpoints_at(m_layers_z_range[1]).last < id) + continue; + + top_layer_endpoints.first = std::min(top_layer_endpoints.first, id); + top_layer_endpoints.last = std::max(top_layer_endpoints.last, id); + } + } +#else for (const TBuffer::Model::Instance& inst : buffer.model.instances) { if (inst.s_id < m_layers.get_endpoints_at(m_layers_z_range[0]).first || m_layers.get_endpoints_at(m_layers_z_range[1]).last < inst.s_id) continue; @@ -2152,6 +2239,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool top_layer_endpoints.last = std::max(top_layer_endpoints.last, inst.s_id); } } +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS } else { #endif // ENABLE_SEAMS_USING_MODELS @@ -2202,6 +2290,20 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool for (const TBuffer& buffer : m_buffers) { #if ENABLE_SEAMS_USING_MODELS if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + for (size_t i = 0; i < buffer.model.instances2.s_ids.size(); ++i) { + if (buffer.model.instances2.s_ids[i] == m_sequential_view.current.last) { + + // gets the position from the vertices buffer on gpu + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, buffer.model.instances2.vbo)); + glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(i * buffer.model.instances2.instance_size_bytes()), static_cast(3 * sizeof(float)), static_cast(sequential_view->current_position.data()))); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + + found = true; + break; + } + } +#else for (const TBuffer::Model::Instance& inst : buffer.model.instances) { if (inst.s_id == m_sequential_view.current.last) { sequential_view->current_position = inst.position; @@ -2209,6 +2311,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool break; } } +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS } else { #endif // ENABLE_SEAMS_USING_MODELS @@ -2357,6 +2460,33 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool #endif } +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + // second pass: for buffers using instanced models, update the instances render ranges + for (size_t b = 0; b < m_buffers.size(); ++b) { + TBuffer& buffer = const_cast(m_buffers[b]); + if (buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) + continue; + + buffer.model.instances2.render_range = { 0, 0 }; + + if (!buffer.visible) + continue; + + if (m_sequential_view.current.first <= buffer.model.instances2.s_ids.back() && buffer.model.instances2.s_ids.front() <= m_sequential_view.current.last) { + for (size_t id : buffer.model.instances2.s_ids) { + if (id <= m_sequential_view.current.first) { + buffer.model.instances2.render_range.offset += buffer.model.instances2.instance_size_bytes(); + buffer.model.instances2.render_range.count = 0; + } + else if (id <= m_sequential_view.current.last) + ++buffer.model.instances2.render_range.count; + else + break; + } + } + } +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS + // set sequential data to their final value sequential_view->endpoints = top_layer_only ? top_layer_endpoints : global_endpoints; sequential_view->current.first = !top_layer_only && keep_sequential_current_first ? std::clamp(sequential_view->current.first, sequential_view->endpoints.first, sequential_view->endpoints.last) : sequential_view->endpoints.first; @@ -2485,7 +2615,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool statistics->render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.offsets, size_t); } #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances2.s_ids, size_t); +#else statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances, TBuffer::Model::Instance); +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_SEAMS_USING_MODELS } statistics->refresh_paths_time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); @@ -3684,9 +3818,15 @@ void GCodeViewer::render_statistics() if (ImGui::CollapsingHeader("GPU memory")) { add_memory(std::string("Vertices:"), m_statistics.total_vertices_gpu_size); add_memory(std::string("Indices:"), m_statistics.total_indices_gpu_size); +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + add_memory(std::string("Instances:"), m_statistics.total_instances_gpu_size); +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS ImGui::Separator(); add_memory(std::string("Max VBuffer:"), m_statistics.max_vbuffer_gpu_size); add_memory(std::string("Max IBuffer:"), m_statistics.max_ibuffer_gpu_size); +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + add_memory(std::string("Max instance VBuffer:"), m_statistics.max_instance_vbuffer_gpu_size); +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS } if (ImGui::CollapsingHeader("Other")) { diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 6103f9722..7bf341a68 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -27,6 +27,10 @@ class GCodeViewer using MultiVertexBuffer = std::vector; using IndexBuffer = std::vector; using MultiIndexBuffer = std::vector; +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + using InstanceBuffer = std::vector; + using InstanceIdBuffer = std::vector; +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS static const std::vector Extrusion_Role_Colors; static const std::vector Options_Colors; @@ -100,6 +104,34 @@ class GCodeViewer void reset(); }; +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + // vbo buffer containing instances data used to render a toolpaths using instanced models + // record format: 5 floats -> position.x|position.y|position.z|width|height + struct InstanceVBuffer + { + struct RenderRange + { + // offset in bytes of the 1st instance to render + unsigned int offset; + // count of instances to render + unsigned int count; + }; + + // vbo id + unsigned int vbo{ 0 }; + // move ids + std::vector s_ids; + RenderRange render_range; + + size_t data_size_bytes() const { return s_ids.size() * instance_size_bytes(); } + + size_t instance_size_floats() const { return 5; } + size_t instance_size_bytes() const { return instance_size_floats() * sizeof(float); } + + void reset(); + }; +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS + // ibo buffer containing indices data (for lines/triangles) used to render a specific toolpath type struct IBuffer { @@ -262,6 +294,9 @@ class GCodeViewer GLModel model; Color color; Instances instances; +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + InstanceVBuffer instances2; +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS void reset(); }; @@ -489,8 +524,14 @@ class GCodeViewer int64_t results_size{ 0 }; int64_t total_vertices_gpu_size{ 0 }; int64_t total_indices_gpu_size{ 0 }; +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + int64_t total_instances_gpu_size{ 0 }; +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS int64_t max_vbuffer_gpu_size{ 0 }; int64_t max_ibuffer_gpu_size{ 0 }; +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + int64_t max_instance_vbuffer_gpu_size{ 0 }; +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS int64_t paths_size{ 0 }; int64_t render_paths_size{ 0 }; #if ENABLE_SEAMS_USING_MODELS @@ -537,8 +578,14 @@ class GCodeViewer results_size = 0; total_vertices_gpu_size = 0; total_indices_gpu_size = 0; +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + total_instances_gpu_size = 0; +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS max_vbuffer_gpu_size = 0; max_ibuffer_gpu_size = 0; +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + max_instance_vbuffer_gpu_size = 0; +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS paths_size = 0; render_paths_size = 0; #if ENABLE_SEAMS_USING_MODELS From 79e8e8627f403fc442d831b8a087528b7951c427 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 20 Aug 2021 11:24:48 +0200 Subject: [PATCH 13/60] Tech ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT - fixed export/import to/from 3mf file of mirrored volumes --- src/libslic3r/Format/3mf.cpp | 27 +++++++++++++++++++++++++++ src/libslic3r/Technologies.hpp | 2 ++ 2 files changed, 29 insertions(+) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 2a76f218f..febeacdbe 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -1839,11 +1839,17 @@ namespace Slic3r { Transform3d volume_matrix_to_object = Transform3d::Identity(); bool has_transform = false; +#if ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT + bool is_left_handed = false; +#endif // ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT // extract the volume transformation from the volume's metadata, if present for (const Metadata& metadata : volume_data.metadata) { if (metadata.key == MATRIX_KEY) { volume_matrix_to_object = Slic3r::Geometry::transform3d_from_string(metadata.value); has_transform = ! volume_matrix_to_object.isApprox(Transform3d::Identity(), 1e-10); +#if ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT + is_left_handed = Slic3r::Geometry::Transformation(volume_matrix_to_object).is_left_handed(); +#endif // ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT break; } } @@ -1875,6 +1881,13 @@ namespace Slic3r { stl_get_size(&stl); triangle_mesh.repair(); +#if ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT + // PrusaSlicer older than 2.4.0 saved mirrored volumes with reversed winding of the triangles + // This caused the call to TriangleMesh::repair() to reverse all the facets because the calculated volume was negative + if (is_left_handed && stl.stats.facets_reversed > 0 && stl.stats.facets_reversed == stl.stats.original_num_facets) + stl.stats.facets_reversed = 0; +#endif // ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT + if (m_version == 0) { // if the 3mf was not produced by PrusaSlicer and there is only one instance, // bake the transformation into the geometry to allow the reload from disk command @@ -2499,6 +2512,10 @@ namespace Slic3r { if (volume == nullptr) continue; +#if ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT + bool is_left_handed = volume->is_left_handed(); +#endif // ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT + VolumeToOffsetsMap::iterator volume_it = volumes_offsets.find(volume); assert(volume_it != volumes_offsets.end()); @@ -2513,6 +2530,15 @@ namespace Slic3r { { const Vec3i &idx = its.indices[i]; char *ptr = buf; +#if ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT + boost::spirit::karma::generate(ptr, boost::spirit::lit(" <") << TRIANGLE_TAG << + " v1=\"" << boost::spirit::int_ << + "\" v2=\"" << boost::spirit::int_ << + "\" v3=\"" << boost::spirit::int_ << "\"", + idx[is_left_handed ? 2 : 0] + volume_it->second.first_vertex_id, + idx[1] + volume_it->second.first_vertex_id, + idx[is_left_handed ? 0 : 2] + volume_it->second.first_vertex_id); +#else boost::spirit::karma::generate(ptr, boost::spirit::lit(" <") << TRIANGLE_TAG << " v1=\"" << boost::spirit::int_ << "\" v2=\"" << boost::spirit::int_ << @@ -2520,6 +2546,7 @@ namespace Slic3r { idx[0] + volume_it->second.first_vertex_id, idx[1] + volume_it->second.first_vertex_id, idx[2] + volume_it->second.first_vertex_id); +#endif // ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT *ptr = '\0'; output_buffer += buf; } diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index f6366c18e..d337fdc2d 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -47,6 +47,8 @@ #define ENABLE_FIX_IMPORTING_COLOR_PRINT_VIEW_INTO_GCODEVIEWER (1 && ENABLE_2_4_0_ALPHA0) // Enable drawing contours, at cut level, for sinking volumes #define ENABLE_SINKING_CONTOURS (1 && ENABLE_2_4_0_ALPHA0) +// Enable the fix for exporting and importing to/from 3mf file of mirrored volumes +#define ENABLE_FIX_MIRRORED_VOLUMES_3MF_IMPORT_EXPORT (1 && ENABLE_2_4_0_ALPHA0) #endif // _prusaslicer_technologies_h_ From 29804187060529c3fbc55ea737e728fd36be9826 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 26 Aug 2021 12:37:55 +0200 Subject: [PATCH 14/60] ENABLE_SEAMS_USING_INSTANCED_MODELS -> WIP: Render models using glDrawElementsInstanced --- resources/shaders/gouraud_light_instanced.fs | 12 +++ resources/shaders/gouraud_light_instanced.vs | 57 ++++++++++++++ src/libslic3r/Technologies.hpp | 4 - src/slic3r/GUI/GCodeViewer.cpp | 63 ++++++++++++---- src/slic3r/GUI/GCodeViewer.hpp | 28 ++++--- src/slic3r/GUI/GLModel.cpp | 79 ++++++++++++++++++++ src/slic3r/GUI/GLModel.hpp | 3 + src/slic3r/GUI/GLShadersManager.cpp | 14 +++- 8 files changed, 229 insertions(+), 31 deletions(-) create mode 100644 resources/shaders/gouraud_light_instanced.fs create mode 100644 resources/shaders/gouraud_light_instanced.vs diff --git a/resources/shaders/gouraud_light_instanced.fs b/resources/shaders/gouraud_light_instanced.fs new file mode 100644 index 000000000..970185a00 --- /dev/null +++ b/resources/shaders/gouraud_light_instanced.fs @@ -0,0 +1,12 @@ +#version 110 + +uniform vec4 uniform_color; +uniform float emission_factor; + +// x = tainted, y = specular; +varying vec2 intensity; + +void main() +{ + gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a); +} diff --git a/resources/shaders/gouraud_light_instanced.vs b/resources/shaders/gouraud_light_instanced.vs new file mode 100644 index 000000000..5d6a05a6f --- /dev/null +++ b/resources/shaders/gouraud_light_instanced.vs @@ -0,0 +1,57 @@ +#version 110 + +#define INTENSITY_CORRECTION 0.6 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) +#define LIGHT_TOP_SHININESS 20.0 + +// normalized values for (1./1.43, 0.2/1.43, 1./1.43) +const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); +#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) + +#define INTENSITY_AMBIENT 0.3 + +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +// vertex attributes +in vec3 v_position; +in vec3 v_normal; +// instance attributes +in vec3 i_offset; +in vec2 i_scales; +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +// x = tainted, y = specular; +varying vec2 intensity; + +void main() +{ + // First transform the normal into camera space and normalize the result. +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + vec3 eye_normal = normalize(gl_NormalMatrix * v_normal); +// vec3 eye_normal = normalize(gl_NormalMatrix * gl_Normal); +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. + float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0); + + intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + vec4 world_position = vec4(v_position * vec3(vec2(i_scales.x), i_scales.y) + i_offset, 1.0); + vec3 eye_position = (gl_ModelViewMatrix * world_position).xyz; +// vec3 eye_position = (gl_ModelViewMatrix * gl_Vertex).xyz; +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); + + // Perform the same lighting calculation for the 2nd light source (no specular applied). + NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0); + intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; + +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + gl_Position = gl_ProjectionMatrix * vec4(eye_position, 1.0); +// gl_Position = ftransform(); +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +} diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index 79976d4a0..0a6b47397 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -50,10 +50,6 @@ // Enable rendering seams (and other options) in preview using models #define ENABLE_SEAMS_USING_MODELS (1 && ENABLE_2_4_0_ALPHA0) // Enable rendering seams (and other options) in preview using instanced models -// references: -// https://ogldev.org/www/tutorial33/tutorial33.html -// https://docs.gl/gl3/glDrawElementsInstanced -// https://www.khronos.org/opengl/wiki/Vertex_Rendering#Instancing #define ENABLE_SEAMS_USING_INSTANCED_MODELS (1 && ENABLE_SEAMS_USING_MODELS) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index b8388f82f..f045cd72a 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -102,7 +102,8 @@ void GCodeViewer::InstanceVBuffer::reset() if (vbo > 0) glsafe(::glDeleteBuffers(1, &vbo)); s_ids.clear(); - render_range = { 0, 0 }; + buffer.clear(); + render_ranges.clear(); } #endif // ENABLE_SEAMS_USING_INSTANCED_MODELS @@ -803,7 +804,11 @@ void GCodeViewer::render() #if ENABLE_SEAMS_USING_MODELS if (wxGetApp().is_gl_version_greater_or_equal_to(3, 1)) { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Model; +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + buffer.shader = "gouraud_light_instanced"; +#else buffer.shader = "gouraud_light"; +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS buffer.model.model.init_from(diamond(16)); buffer.model.color = option_color(type); } @@ -1764,7 +1769,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) #if ENABLE_GCODE_VIEWER_STATISTICS m_statistics.total_instances_gpu_size += static_cast(size_bytes); - m_statistics.max_instance_vbuffer_gpu_size = std::max(m_statistics.max_instance_vbuffer_gpu_size, static_cast(size_bytes)); #endif // ENABLE_GCODE_VIEWER_STATISTICS GLuint id = 0; @@ -1774,6 +1778,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); t_buffer.model.instances2.vbo = id; + t_buffer.model.instances2.buffer = inst_buffer; t_buffer.model.instances2.s_ids = instances_ids[i]; } } @@ -2467,21 +2472,36 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool if (buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) continue; - buffer.model.instances2.render_range = { 0, 0 }; + buffer.model.instances2.render_ranges.clear(); if (!buffer.visible) continue; + buffer.model.instances2.render_ranges.push_back({ 0, 0, buffer.model.color }); + bool has_second_range = top_layer_only && m_sequential_view.current.last != m_sequential_view.global.last; + if (has_second_range) + buffer.model.instances2.render_ranges.push_back({ 0, 0, Neutral_Color }); + if (m_sequential_view.current.first <= buffer.model.instances2.s_ids.back() && buffer.model.instances2.s_ids.front() <= m_sequential_view.current.last) { for (size_t id : buffer.model.instances2.s_ids) { - if (id <= m_sequential_view.current.first) { - buffer.model.instances2.render_range.offset += buffer.model.instances2.instance_size_bytes(); - buffer.model.instances2.render_range.count = 0; + if (has_second_range) { + if (id <= m_sequential_view.endpoints.first) { + buffer.model.instances2.render_ranges.front().offset += buffer.model.instances2.instance_size_bytes(); + ++buffer.model.instances2.render_ranges.back().count; + } + else if (id <= m_sequential_view.current.last) + ++buffer.model.instances2.render_ranges.front().count; + else + break; + } + else { + if (id <= m_sequential_view.current.first) + buffer.model.instances2.render_ranges.front().offset += buffer.model.instances2.instance_size_bytes(); + else if (id <= m_sequential_view.current.last) + ++buffer.model.instances2.render_ranges.front().count; + else + break; } - else if (id <= m_sequential_view.current.last) - ++buffer.model.instances2.render_range.count; - else - break; } } } @@ -2616,7 +2636,9 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool } #if ENABLE_SEAMS_USING_MODELS #if ENABLE_SEAMS_USING_INSTANCED_MODELS + statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances2.buffer, float); statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances2.s_ids, size_t); + statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances2.render_ranges, InstanceVBuffer::RenderRange); #else statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances, TBuffer::Model::Instance); #endif // ENABLE_SEAMS_USING_INSTANCED_MODELS @@ -2711,7 +2733,18 @@ void GCodeViewer::render_toolpaths() #if ENABLE_SEAMS_USING_MODELS auto render_as_instanced_model = [this] - (TBuffer & buffer, GLShaderProgram & shader) { + (TBuffer& buffer, GLShaderProgram & shader) { +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + if (buffer.model.instances2.vbo > 0) { + for (const InstanceVBuffer::RenderRange& range : buffer.model.instances2.render_ranges) { + buffer.model.model.set_color(-1, range.color); + buffer.model.model.render_instanced(buffer.model.instances2.vbo, range.count); +#if ENABLE_GCODE_VIEWER_STATISTICS + ++m_statistics.gl_instanced_models_calls_count; +#endif // ENABLE_GCODE_VIEWER_STATISTICS + } + } +#else for (const TBuffer::Model::Instance& inst : buffer.model.instances) { bool top_layer_only = get_app_config()->get("seq_top_layer_only") == "1"; bool visible = top_layer_only ? @@ -2732,6 +2765,7 @@ void GCodeViewer::render_toolpaths() #endif // ENABLE_GCODE_VIEWER_STATISTICS } } +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS }; #endif // ENABLE_SEAMS_USING_MODELS @@ -3800,7 +3834,11 @@ void GCodeViewer::render_statistics() add_counter(std::string("Multi GL_TRIANGLES:"), m_statistics.gl_multi_triangles_calls_count); add_counter(std::string("GL_TRIANGLES:"), m_statistics.gl_triangles_calls_count); #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + add_counter(std::string("Instanced models:"), m_statistics.gl_instanced_models_calls_count); +#else add_counter(std::string("Models:"), m_statistics.gl_models_calls_count); +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_SEAMS_USING_MODELS } @@ -3824,9 +3862,6 @@ void GCodeViewer::render_statistics() ImGui::Separator(); add_memory(std::string("Max VBuffer:"), m_statistics.max_vbuffer_gpu_size); add_memory(std::string("Max IBuffer:"), m_statistics.max_ibuffer_gpu_size); -#if ENABLE_SEAMS_USING_INSTANCED_MODELS - add_memory(std::string("Max instance VBuffer:"), m_statistics.max_instance_vbuffer_gpu_size); -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS } if (ImGui::CollapsingHeader("Other")) { diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 7bf341a68..bda0491de 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -105,8 +105,9 @@ class GCodeViewer }; #if ENABLE_SEAMS_USING_INSTANCED_MODELS - // vbo buffer containing instances data used to render a toolpaths using instanced models - // record format: 5 floats -> position.x|position.y|position.z|width|height + // buffer containing instances data used to render a toolpaths using instanced models + // instance record format: 5 floats -> position.x|position.y|position.z|width|height + // which is sent to the shader as -> vec3 (offset) + vec2 (scales) in GLModel::render_instanced() struct InstanceVBuffer { struct RenderRange @@ -115,13 +116,18 @@ class GCodeViewer unsigned int offset; // count of instances to render unsigned int count; + // Color to apply to the instances + Color color; }; // vbo id unsigned int vbo{ 0 }; - // move ids + // cpu-side buffer containing all instances data + InstanceBuffer buffer; + // indices of the moves for all instances std::vector s_ids; - RenderRange render_range; + // ranges used to render only subparts of the intances + std::vector render_ranges; size_t data_size_bytes() const { return s_ids.size() * instance_size_bytes(); } @@ -518,7 +524,11 @@ class GCodeViewer int64_t gl_multi_triangles_calls_count{ 0 }; int64_t gl_triangles_calls_count{ 0 }; #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + int64_t gl_instanced_models_calls_count{ 0 }; +#else int64_t gl_models_calls_count{ 0 }; +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_SEAMS_USING_MODELS // memory int64_t results_size{ 0 }; @@ -529,9 +539,6 @@ class GCodeViewer #endif // ENABLE_SEAMS_USING_INSTANCED_MODELS int64_t max_vbuffer_gpu_size{ 0 }; int64_t max_ibuffer_gpu_size{ 0 }; -#if ENABLE_SEAMS_USING_INSTANCED_MODELS - int64_t max_instance_vbuffer_gpu_size{ 0 }; -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS int64_t paths_size{ 0 }; int64_t render_paths_size{ 0 }; #if ENABLE_SEAMS_USING_MODELS @@ -570,7 +577,11 @@ class GCodeViewer gl_multi_triangles_calls_count = 0; gl_triangles_calls_count = 0; #if ENABLE_SEAMS_USING_MODELS +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + gl_instanced_models_calls_count = 0; +#else gl_models_calls_count = 0; +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_SEAMS_USING_MODELS } @@ -583,9 +594,6 @@ class GCodeViewer #endif // ENABLE_SEAMS_USING_INSTANCED_MODELS max_vbuffer_gpu_size = 0; max_ibuffer_gpu_size = 0; -#if ENABLE_SEAMS_USING_INSTANCED_MODELS - max_instance_vbuffer_gpu_size = 0; -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS paths_size = 0; render_paths_size = 0; #if ENABLE_SEAMS_USING_MODELS diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index c4437a87f..58dfcb68b 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -207,6 +207,85 @@ void GLModel::render() const } } +#if ENABLE_SEAMS_USING_INSTANCED_MODELS +void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instances_count) const +{ + if (instances_vbo == 0) + return; + + GLShaderProgram* shader = wxGetApp().get_current_shader(); + assert(shader == nullptr || boost::algorithm::iends_with(shader->get_name(), "_instanced")); + + // vertex attributes + GLint position_id = (shader != nullptr) ? shader->get_attrib_location("v_position") : -1; + GLint normal_id = (shader != nullptr) ? shader->get_attrib_location("v_normal") : -1; + assert(position_id != -1 && normal_id != -1); + + // instance attributes + GLint offset_id = (shader != nullptr) ? shader->get_attrib_location("i_offset") : -1; + GLint scales_id = (shader != nullptr) ? shader->get_attrib_location("i_scales") : -1; + assert(offset_id != -1 && scales_id != -1); + + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, instances_vbo)); + if (offset_id != -1) { + glsafe(::glVertexAttribPointer(offset_id, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (GLvoid*)0)); + glsafe(::glEnableVertexAttribArray(offset_id)); + glsafe(::glVertexAttribDivisor(offset_id, 1)); + } + if (scales_id != -1) { + glsafe(::glVertexAttribPointer(scales_id, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (GLvoid*)(3 * sizeof(float)))); + glsafe(::glEnableVertexAttribArray(scales_id)); + glsafe(::glVertexAttribDivisor(scales_id, 1)); + } + + for (const RenderData& data : m_render_data) { + if (data.vbo_id == 0 || data.ibo_id == 0) + continue; + + GLenum mode; + switch (data.type) + { + default: + case PrimitiveType::Triangles: { mode = GL_TRIANGLES; break; } + case PrimitiveType::Lines: { mode = GL_LINES; break; } + case PrimitiveType::LineStrip: { mode = GL_LINE_STRIP; break; } + case PrimitiveType::LineLoop: { mode = GL_LINE_LOOP; break; } + } + + if (shader != nullptr) + shader->set_uniform("uniform_color", data.color); + else + glsafe(::glColor4fv(data.color.data())); + + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, data.vbo_id)); + if (position_id != -1) { + glsafe(::glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (GLvoid*)0)); + glsafe(::glEnableVertexAttribArray(position_id)); + } + if (normal_id != -1) { + glsafe(::glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (GLvoid*)(3 * sizeof(float)))); + glsafe(::glEnableVertexAttribArray(normal_id)); + } + + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ibo_id)); + glsafe(::glDrawElementsInstanced(mode, static_cast(data.indices_count), GL_UNSIGNED_INT, (const void*)0, instances_count)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + + if (normal_id != -1) + glsafe(::glDisableVertexAttribArray(normal_id)); + if (position_id != -1) + glsafe(::glDisableVertexAttribArray(position_id)); + } + + if (scales_id != -1) + glsafe(::glDisableVertexAttribArray(scales_id)); + if (offset_id != -1) + glsafe(::glDisableVertexAttribArray(offset_id)); + + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); +} +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS + void GLModel::send_to_gpu(RenderData& data, const std::vector& vertices, const std::vector& indices) { assert(data.vbo_id == 0); diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index 99c4bf442..73fb90827 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -72,6 +72,9 @@ namespace GUI { void reset(); void render() const; +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + void render_instanced(unsigned int instances_vbo, unsigned int instances_count) const; +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS bool is_initialized() const { return !m_render_data.empty(); } diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index 788fe90c0..7bb0a50a6 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -38,9 +38,17 @@ std::pair GLShadersManager::init() // used to render printbed valid &= append_shader("printbed", { "printbed.vs", "printbed.fs" }); // used to render options in gcode preview - valid &= append_shader("options_110", { "options_110.vs", "options_110.fs" }); - if (GUI::wxGetApp().is_glsl_version_greater_or_equal_to(1, 20)) - valid &= append_shader("options_120", { "options_120.vs", "options_120.fs" }); +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 1)) + valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); + else { +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS + valid &= append_shader("options_110", { "options_110.vs", "options_110.fs" }); + if (GUI::wxGetApp().is_glsl_version_greater_or_equal_to(1, 20)) + valid &= append_shader("options_120", { "options_120.vs", "options_120.fs" }); +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + } +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS // used to render extrusion and travel paths as lines in gcode preview valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" }); // used to render objects in 3d editor From 9cffbc929ef5be72741b0698ee58cb40bed74a9d Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 26 Aug 2021 13:39:22 +0200 Subject: [PATCH 15/60] Fix unsliced objects when their dimensions are close to bed limits fixes #6823 --- src/slic3r/GUI/Plater.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 1841220d5..d315e7734 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2915,6 +2915,7 @@ void Plater::priv::update_print_volume_state() BoundingBox bed_box_2D = get_extents(Polygon::new_scale(this->config->opt("bed_shape")->values)); BoundingBoxf3 print_volume(unscale(bed_box_2D.min(0), bed_box_2D.min(1), 0.0), unscale(bed_box_2D.max(0), bed_box_2D.max(1), scale_(this->config->opt_float("max_print_height")))); // Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced. + print_volume.offset(BedEpsilon); print_volume.min(2) = -1e10; this->q->model().update_print_volume_state(print_volume); } From 9f70afe44e3af9b9e11760f9dad1e40a14d9f1c1 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Thu, 26 Aug 2021 14:21:54 +0200 Subject: [PATCH 16/60] Fix: Do not revert changes on change GLGizmoBase::m_state when apply was used --- src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp | 29 ++++++++++++----------- src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp | 1 + 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index 5ce0064db..d4e14c6f4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -199,7 +199,7 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi ImGui::SameLine(m_gui_cfg->bottom_left_width); if (m_imgui->button(_L("Preview"))) { m_state = State::preview; - // simplify but not aply on mesh + // simplify but not apply on mesh process(); } ImGui::SameLine(); @@ -207,15 +207,12 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi if (!m_is_valid_result) { m_state = State::close_on_end; process(); - } else { + } else if (m_exist_preview) { // use preview and close - if (m_exist_preview) { - // fix hollowing, sla support points, modifiers, ... - auto plater = wxGetApp().plater(); - plater->changed_mesh(m_obj_index); - } + after_apply(); + } else { // no changes made close(); - } + } } } else { m_imgui->disabled_begin(m_state == State::canceling); @@ -237,18 +234,22 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi m_parent.reload_scene(true); // set m_state must be before close() !!! m_state = State::settings; - if (close_on_end) { - // fix hollowing, sla support points, modifiers, ... - auto plater = wxGetApp().plater(); - plater->changed_mesh(m_obj_index); - close(); - } + if (close_on_end) after_apply(); // Fix warning icon in object list wxGetApp().obj_list()->update_item_error_icon(m_obj_index, -1); } } +void GLGizmoSimplify::after_apply() { + // set flag to NOT revert changes when switch GLGizmoBase::m_state + m_exist_preview = false; + // fix hollowing, sla support points, modifiers, ... + auto plater = wxGetApp().plater(); + plater->changed_mesh(m_obj_index); + close(); +} + void GLGizmoSimplify::close() { // close gizmo == open it again GLGizmosManager &gizmos_mgr = m_parent.get_gizmos_manager(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp index 1b25c4ac9..0f5bd5991 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.hpp @@ -32,6 +32,7 @@ protected: virtual void on_set_state() override; private: + void after_apply(); void close(); void process(); void set_its(indexed_triangle_set &its); From c471c3c7c41b3163a276e3fd2aaa2a312d9185f3 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 26 Aug 2021 14:37:09 +0200 Subject: [PATCH 17/60] Code cleanup and small refactoring --- src/slic3r/GUI/GCodeViewer.cpp | 81 ++++++++++++++++++---------------- src/slic3r/GUI/GCodeViewer.hpp | 11 ++++- 2 files changed, 51 insertions(+), 41 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index f045cd72a..b6cac4059 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -151,9 +151,10 @@ bool GCodeViewer::Path::matches(const GCodeProcessor::MoveVertex& move) const #if ENABLE_SEAMS_USING_MODELS void GCodeViewer::TBuffer::Model::reset() { - instances.clear(); #if ENABLE_SEAMS_USING_INSTANCED_MODELS - instances2.reset(); + instances.reset(); +#else + instances.clear(); #endif // ENABLE_SEAMS_USING_INSTANCED_MODELS } #endif // ENABLE_SEAMS_USING_MODELS @@ -1432,19 +1433,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) }; #if ENABLE_SEAMS_USING_MODELS - // format data into the buffers to be rendered as model - auto add_model_instance = [](const GCodeProcessor::MoveVertex& curr, TBuffer::Model::Instances& instances, size_t move_id) { - TBuffer::Model::Instance instance; - instance.position = curr.position; - instance.width = 1.2f * curr.width; - instance.height = 1.2f * curr.height; - instance.s_id = move_id; - instances.emplace_back(instance); - }; - #if ENABLE_SEAMS_USING_INSTANCED_MODELS // format data into the buffers to be rendered as model - auto add_model_instance_2 = [](const GCodeProcessor::MoveVertex& curr, InstanceBuffer& instances, InstanceIdBuffer& instances_ids, size_t move_id) { + auto add_model_instance = [](const GCodeProcessor::MoveVertex& curr, InstanceBuffer& instances, InstanceIdBuffer& instances_ids, size_t move_id) { // append position instances.push_back(curr.position.x()); instances.push_back(curr.position.y()); @@ -1457,6 +1448,15 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // append id instances_ids.push_back(move_id); }; +#else + auto add_model_instance = [](const GCodeProcessor::MoveVertex& curr, TBuffer::Model::Instances& instances, size_t move_id) { + TBuffer::Model::Instance instance; + instance.position = curr.position; + instance.width = 1.2f * curr.width; + instance.height = 1.2f * curr.height; + instance.s_id = move_id; + instances.emplace_back(instance); + }; #endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_SEAMS_USING_MODELS @@ -1560,9 +1560,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) #if ENABLE_SEAMS_USING_MODELS case TBuffer::ERenderPrimitiveType::Model: { - add_model_instance(curr, t_buffer.model.instances, i); #if ENABLE_SEAMS_USING_INSTANCED_MODELS - add_model_instance_2(curr, inst_buffer, inst_id_buffer, i); + add_model_instance(curr, inst_buffer, inst_id_buffer, i); +#else + add_model_instance(curr, t_buffer.model.instances, i); #endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.instances_count; @@ -1741,12 +1742,14 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) } #if ENABLE_SEAMS_USING_MODELS +#if !ENABLE_SEAMS_USING_INSTANCED_MODELS for (size_t i = 0; i < m_buffers.size(); ++i) { TBuffer& t_buffer = m_buffers[i]; if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { t_buffer.model.instances.shrink_to_fit(); } } +#endif // !ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_SEAMS_USING_MODELS // move the wipe toolpaths half height up to render them on proper position @@ -1777,9 +1780,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) glsafe(::glBufferData(GL_ARRAY_BUFFER, size_bytes, inst_buffer.data(), GL_STATIC_DRAW)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); - t_buffer.model.instances2.vbo = id; - t_buffer.model.instances2.buffer = inst_buffer; - t_buffer.model.instances2.s_ids = instances_ids[i]; + t_buffer.model.instances.vbo = id; + t_buffer.model.instances.buffer = inst_buffer; + t_buffer.model.instances.s_ids = instances_ids[i]; } } else { @@ -2213,7 +2216,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool #if ENABLE_SEAMS_USING_MODELS if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { #if ENABLE_SEAMS_USING_INSTANCED_MODELS - for (size_t id : buffer.model.instances2.s_ids) { + for (size_t id : buffer.model.instances.s_ids) { if (id < m_layers.get_endpoints_at(m_layers_z_range[0]).first || m_layers.get_endpoints_at(m_layers_z_range[1]).last < id) continue; @@ -2296,12 +2299,12 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool #if ENABLE_SEAMS_USING_MODELS if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { #if ENABLE_SEAMS_USING_INSTANCED_MODELS - for (size_t i = 0; i < buffer.model.instances2.s_ids.size(); ++i) { - if (buffer.model.instances2.s_ids[i] == m_sequential_view.current.last) { + for (size_t i = 0; i < buffer.model.instances.s_ids.size(); ++i) { + if (buffer.model.instances.s_ids[i] == m_sequential_view.current.last) { // gets the position from the vertices buffer on gpu - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, buffer.model.instances2.vbo)); - glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(i * buffer.model.instances2.instance_size_bytes()), static_cast(3 * sizeof(float)), static_cast(sequential_view->current_position.data()))); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, buffer.model.instances.vbo)); + glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(i * buffer.model.instances.instance_size_bytes()), static_cast(3 * sizeof(float)), static_cast(sequential_view->current_position.data()))); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); found = true; @@ -2472,33 +2475,33 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool if (buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) continue; - buffer.model.instances2.render_ranges.clear(); + buffer.model.instances.render_ranges.clear(); if (!buffer.visible) continue; - buffer.model.instances2.render_ranges.push_back({ 0, 0, buffer.model.color }); + buffer.model.instances.render_ranges.push_back({ 0, 0, buffer.model.color }); bool has_second_range = top_layer_only && m_sequential_view.current.last != m_sequential_view.global.last; if (has_second_range) - buffer.model.instances2.render_ranges.push_back({ 0, 0, Neutral_Color }); + buffer.model.instances.render_ranges.push_back({ 0, 0, Neutral_Color }); - if (m_sequential_view.current.first <= buffer.model.instances2.s_ids.back() && buffer.model.instances2.s_ids.front() <= m_sequential_view.current.last) { - for (size_t id : buffer.model.instances2.s_ids) { + if (m_sequential_view.current.first <= buffer.model.instances.s_ids.back() && buffer.model.instances.s_ids.front() <= m_sequential_view.current.last) { + for (size_t id : buffer.model.instances.s_ids) { if (has_second_range) { if (id <= m_sequential_view.endpoints.first) { - buffer.model.instances2.render_ranges.front().offset += buffer.model.instances2.instance_size_bytes(); - ++buffer.model.instances2.render_ranges.back().count; + buffer.model.instances.render_ranges.front().offset += buffer.model.instances.instance_size_bytes(); + ++buffer.model.instances.render_ranges.back().count; } else if (id <= m_sequential_view.current.last) - ++buffer.model.instances2.render_ranges.front().count; + ++buffer.model.instances.render_ranges.front().count; else break; } else { if (id <= m_sequential_view.current.first) - buffer.model.instances2.render_ranges.front().offset += buffer.model.instances2.instance_size_bytes(); + buffer.model.instances.render_ranges.front().offset += buffer.model.instances.instance_size_bytes(); else if (id <= m_sequential_view.current.last) - ++buffer.model.instances2.render_ranges.front().count; + ++buffer.model.instances.render_ranges.front().count; else break; } @@ -2636,9 +2639,9 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool } #if ENABLE_SEAMS_USING_MODELS #if ENABLE_SEAMS_USING_INSTANCED_MODELS - statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances2.buffer, float); - statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances2.s_ids, size_t); - statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances2.render_ranges, InstanceVBuffer::RenderRange); + statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances.buffer, float); + statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances.s_ids, size_t); + statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances.render_ranges, InstanceVBuffer::RenderRange); #else statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances, TBuffer::Model::Instance); #endif // ENABLE_SEAMS_USING_INSTANCED_MODELS @@ -2735,10 +2738,10 @@ void GCodeViewer::render_toolpaths() auto render_as_instanced_model = [this] (TBuffer& buffer, GLShaderProgram & shader) { #if ENABLE_SEAMS_USING_INSTANCED_MODELS - if (buffer.model.instances2.vbo > 0) { - for (const InstanceVBuffer::RenderRange& range : buffer.model.instances2.render_ranges) { + if (buffer.model.instances.vbo > 0) { + for (const InstanceVBuffer::RenderRange& range : buffer.model.instances.render_ranges) { buffer.model.model.set_color(-1, range.color); - buffer.model.model.render_instanced(buffer.model.instances2.vbo, range.count); + buffer.model.model.render_instanced(buffer.model.instances.vbo, range.count); #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_instanced_models_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index bda0491de..3e5e50c82 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -288,6 +288,7 @@ class GCodeViewer #if ENABLE_SEAMS_USING_MODELS struct Model { +#if !ENABLE_SEAMS_USING_INSTANCED_MODELS struct Instance { Vec3f position; @@ -296,12 +297,14 @@ class GCodeViewer size_t s_id; }; using Instances = std::vector; +#endif // !ENABLE_SEAMS_USING_INSTANCED_MODELS GLModel model; Color color; - Instances instances; #if ENABLE_SEAMS_USING_INSTANCED_MODELS - InstanceVBuffer instances2; + InstanceVBuffer instances; +#else + Instances instances; #endif // ENABLE_SEAMS_USING_INSTANCED_MODELS void reset(); @@ -367,7 +370,11 @@ class GCodeViewer case ERenderPrimitiveType::Triangle: { return !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; } +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + case ERenderPrimitiveType::Model: { return model.model.is_initialized() && !model.instances.buffer.empty(); } +#else case ERenderPrimitiveType::Model: { return model.model.is_initialized() && !model.instances.empty(); } +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS default: { return false; } } } From 03dc2f7c11b128cbef4610f0f70063bf930eff35 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 27 Aug 2021 10:16:50 +0200 Subject: [PATCH 18/60] ENABLE_SEAMS_USING_INSTANCED_MODELS -> Completed implementation of rendering models using instancing --- src/slic3r/GUI/GCodeViewer.cpp | 83 ++++++++++++++++++++-------------- src/slic3r/GUI/GCodeViewer.hpp | 29 +++++++----- 2 files changed, 67 insertions(+), 45 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index b6cac4059..c672f9060 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -96,14 +96,22 @@ void GCodeViewer::VBuffer::reset() } #if ENABLE_SEAMS_USING_INSTANCED_MODELS +void GCodeViewer::InstanceVBuffer::Ranges::reset() +{ + for (Range& range : ranges) { + // release gpu memory + if (range.vbo > 0) + glsafe(::glDeleteBuffers(1, &range.vbo)); + } + + ranges.clear(); +} + void GCodeViewer::InstanceVBuffer::reset() { - // release gpu memory - if (vbo > 0) - glsafe(::glDeleteBuffers(1, &vbo)); s_ids.clear(); buffer.clear(); - render_ranges.clear(); + render_ranges.reset(); } #endif // ENABLE_SEAMS_USING_INSTANCED_MODELS @@ -862,6 +870,9 @@ void GCodeViewer::render() #if ENABLE_GCODE_VIEWER_STATISTICS m_statistics.reset_opengl(); +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + m_statistics.total_instances_gpu_size = 0; +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_GCODE_VIEWER_STATISTICS // OpenGL data must be initialized after the glContext has been created. @@ -1760,7 +1771,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) } } +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + // send vertices data to gpu, where needed +#else // send vertices data to gpu +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS for (size_t i = 0; i < m_buffers.size(); ++i) { TBuffer& t_buffer = m_buffers[i]; #if ENABLE_SEAMS_USING_MODELS @@ -1768,19 +1783,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { const InstanceBuffer& inst_buffer = instances[i]; if (!inst_buffer.empty()) { - const size_t size_bytes = inst_buffer.size() * sizeof(float); - -#if ENABLE_GCODE_VIEWER_STATISTICS - m_statistics.total_instances_gpu_size += static_cast(size_bytes); -#endif // ENABLE_GCODE_VIEWER_STATISTICS - - GLuint id = 0; - glsafe(::glGenBuffers(1, &id)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, id)); - glsafe(::glBufferData(GL_ARRAY_BUFFER, size_bytes, inst_buffer.data(), GL_STATIC_DRAW)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); - - t_buffer.model.instances.vbo = id; t_buffer.model.instances.buffer = inst_buffer; t_buffer.model.instances.s_ids = instances_ids[i]; } @@ -2293,7 +2295,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool sequential_view->current.first = !top_layer_only && keep_sequential_current_first ? std::clamp(sequential_view->current.first, global_endpoints.first, global_endpoints.last) : global_endpoints.first; sequential_view->current.last = keep_sequential_current_last ? std::clamp(sequential_view->current.last, global_endpoints.first, global_endpoints.last) : global_endpoints.last; +#if ENABLE_SEAMS_USING_INSTANCED_MODELS + // get the world position from the vertex buffer +#else // get the world position from gpu +#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS bool found = false; for (const TBuffer& buffer : m_buffers) { #if ENABLE_SEAMS_USING_MODELS @@ -2301,11 +2307,10 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool #if ENABLE_SEAMS_USING_INSTANCED_MODELS for (size_t i = 0; i < buffer.model.instances.s_ids.size(); ++i) { if (buffer.model.instances.s_ids[i] == m_sequential_view.current.last) { - - // gets the position from the vertices buffer on gpu - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, buffer.model.instances.vbo)); - glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(i * buffer.model.instances.instance_size_bytes()), static_cast(3 * sizeof(float)), static_cast(sequential_view->current_position.data()))); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + size_t offset = i * buffer.model.instances.instance_size_floats(); + sequential_view->current_position.x() = buffer.model.instances.buffer[offset + 0]; + sequential_view->current_position.y() = buffer.model.instances.buffer[offset + 1]; + sequential_view->current_position.z() = buffer.model.instances.buffer[offset + 2]; found = true; break; @@ -2475,33 +2480,33 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool if (buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) continue; - buffer.model.instances.render_ranges.clear(); + buffer.model.instances.render_ranges.reset(); if (!buffer.visible) continue; - buffer.model.instances.render_ranges.push_back({ 0, 0, buffer.model.color }); + buffer.model.instances.render_ranges.ranges.push_back({ 0, 0, 0, buffer.model.color }); bool has_second_range = top_layer_only && m_sequential_view.current.last != m_sequential_view.global.last; if (has_second_range) - buffer.model.instances.render_ranges.push_back({ 0, 0, Neutral_Color }); + buffer.model.instances.render_ranges.ranges.push_back({ 0, 0, 0, Neutral_Color }); if (m_sequential_view.current.first <= buffer.model.instances.s_ids.back() && buffer.model.instances.s_ids.front() <= m_sequential_view.current.last) { for (size_t id : buffer.model.instances.s_ids) { if (has_second_range) { if (id <= m_sequential_view.endpoints.first) { - buffer.model.instances.render_ranges.front().offset += buffer.model.instances.instance_size_bytes(); - ++buffer.model.instances.render_ranges.back().count; + ++buffer.model.instances.render_ranges.ranges.front().offset; + ++buffer.model.instances.render_ranges.ranges.back().count; } else if (id <= m_sequential_view.current.last) - ++buffer.model.instances.render_ranges.front().count; + ++buffer.model.instances.render_ranges.ranges.front().count; else break; } else { if (id <= m_sequential_view.current.first) - buffer.model.instances.render_ranges.front().offset += buffer.model.instances.instance_size_bytes(); + ++buffer.model.instances.render_ranges.ranges.front().offset; else if (id <= m_sequential_view.current.last) - ++buffer.model.instances.render_ranges.front().count; + ++buffer.model.instances.render_ranges.ranges.front().count; else break; } @@ -2641,7 +2646,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool #if ENABLE_SEAMS_USING_INSTANCED_MODELS statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances.buffer, float); statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances.s_ids, size_t); - statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances.render_ranges, InstanceVBuffer::RenderRange); + statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances.render_ranges.ranges, InstanceVBuffer::Ranges::Range); #else statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances, TBuffer::Model::Instance); #endif // ENABLE_SEAMS_USING_INSTANCED_MODELS @@ -2738,12 +2743,22 @@ void GCodeViewer::render_toolpaths() auto render_as_instanced_model = [this] (TBuffer& buffer, GLShaderProgram & shader) { #if ENABLE_SEAMS_USING_INSTANCED_MODELS - if (buffer.model.instances.vbo > 0) { - for (const InstanceVBuffer::RenderRange& range : buffer.model.instances.render_ranges) { + for (auto& range : buffer.model.instances.render_ranges.ranges) { + if (range.vbo == 0 && range.count > 0) { + std::cout << range.offset * buffer.model.instances.instance_size_bytes() << " + " << range.count * buffer.model.instances.instance_size_bytes() << " = " << buffer.model.instances.buffer.size() * sizeof(float) << "\n"; + + glsafe(::glGenBuffers(1, &range.vbo)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, range.vbo)); + glsafe(::glBufferData(GL_ARRAY_BUFFER, range.count * buffer.model.instances.instance_size_bytes(), (const void*)&buffer.model.instances.buffer[range.offset * buffer.model.instances.instance_size_floats()], GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + } + + if (range.vbo > 0) { buffer.model.model.set_color(-1, range.color); - buffer.model.model.render_instanced(buffer.model.instances.vbo, range.count); + buffer.model.model.render_instanced(range.vbo, range.count); #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.gl_instanced_models_calls_count; + m_statistics.total_instances_gpu_size += static_cast(range.count * buffer.model.instances.instance_size_bytes()); #endif // ENABLE_GCODE_VIEWER_STATISTICS } } diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 3e5e50c82..46f6558dd 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -110,24 +110,31 @@ class GCodeViewer // which is sent to the shader as -> vec3 (offset) + vec2 (scales) in GLModel::render_instanced() struct InstanceVBuffer { - struct RenderRange + // ranges used to render only subparts of the intances + struct Ranges { - // offset in bytes of the 1st instance to render - unsigned int offset; - // count of instances to render - unsigned int count; - // Color to apply to the instances - Color color; + struct Range + { + // offset in bytes of the 1st instance to render + unsigned int offset; + // count of instances to render + unsigned int count; + // vbo id + unsigned int vbo{ 0 }; + // Color to apply to the instances + Color color; + }; + + std::vector ranges; + + void reset(); }; - // vbo id - unsigned int vbo{ 0 }; // cpu-side buffer containing all instances data InstanceBuffer buffer; // indices of the moves for all instances std::vector s_ids; - // ranges used to render only subparts of the intances - std::vector render_ranges; + Ranges render_ranges; size_t data_size_bytes() const { return s_ids.size() * instance_size_bytes(); } From ae8e0311d796f82b701083677a53962f8af9487c Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 27 Aug 2021 11:25:50 +0200 Subject: [PATCH 19/60] debugging function debug_output_path() moved to utils.cpp/hpp and it now prints to console the default path when called for the first time. Fixed compilation of debugging output in SupportMaterial. --- src/libslic3r/SupportMaterial.cpp | 105 +++++++++++++++--------------- src/libslic3r/Utils.hpp | 5 ++ src/libslic3r/libslic3r.h | 12 ---- src/libslic3r/utils.cpp | 17 +++++ 4 files changed, 75 insertions(+), 64 deletions(-) diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index e2d7bf199..c9794a6c8 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -37,6 +37,7 @@ #define DEBUG #define _DEBUG #undef NDEBUG + #include "utils.hpp" #include "SVG.hpp" #endif @@ -429,7 +430,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) for (const MyLayer *layer : top_contacts) Slic3r::SVG::export_expolygons( debug_out_path("support-top-contacts-%d-%lf.svg", iRun, layer->print_z), - union_ex(layer->polygons, false)); + union_ex(layer->polygons)); #endif /* SLIC3R_DEBUG */ BOOST_LOG_TRIVIAL(info) << "Support generator - Creating bottom contacts"; @@ -447,7 +448,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) for (size_t layer_id = 0; layer_id < object.layers().size(); ++ layer_id) Slic3r::SVG::export_expolygons( debug_out_path("support-areas-%d-%lf.svg", iRun, object.layers()[layer_id]->print_z), - union_ex(layer_support_areas[layer_id], false)); + union_ex(layer_support_areas[layer_id])); #endif /* SLIC3R_DEBUG */ BOOST_LOG_TRIVIAL(info) << "Support generator - Creating intermediate layers - indices"; @@ -466,7 +467,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) for (const MyLayer *layer : top_contacts) Slic3r::SVG::export_expolygons( debug_out_path("support-top-contacts-trimmed-by-object-%d-%lf.svg", iRun, layer->print_z), - union_ex(layer->polygons, false)); + union_ex(layer->polygons)); #endif BOOST_LOG_TRIVIAL(info) << "Support generator - Creating base layers"; @@ -478,7 +479,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) for (MyLayersPtr::const_iterator it = intermediate_layers.begin(); it != intermediate_layers.end(); ++ it) Slic3r::SVG::export_expolygons( debug_out_path("support-base-layers-%d-%lf.svg", iRun, (*it)->print_z), - union_ex((*it)->polygons, false)); + union_ex((*it)->polygons)); #endif /* SLIC3R_DEBUG */ BOOST_LOG_TRIVIAL(info) << "Support generator - Trimming top contacts by bottom contacts"; @@ -507,11 +508,11 @@ void PrintObjectSupportMaterial::generate(PrintObject &object) for (const MyLayer *l : interface_layers) Slic3r::SVG::export_expolygons( debug_out_path("support-interface-layers-%d-%lf.svg", iRun, l->print_z), - union_ex(l->polygons, false)); + union_ex(l->polygons)); for (const MyLayer *l : base_interface_layers) Slic3r::SVG::export_expolygons( debug_out_path("support-base-interface-layers-%d-%lf.svg", iRun, l->print_z), - union_ex(l->polygons, false)); + union_ex(l->polygons)); #endif // SLIC3R_DEBUG /* @@ -1308,9 +1309,9 @@ namespace SupportMaterialInternal { #ifdef SLIC3R_DEBUG static int iRun = 0; SVG::export_expolygons(debug_out_path("support-top-contacts-remove-bridges-run%d.svg", iRun ++), - { { { union_ex(offset(layerm->unsupported_bridge_edges, scale_(SUPPORT_MATERIAL_MARGIN), SUPPORT_SURFACES_OFFSET_PARAMETERS), false) }, { "unsupported_bridge_edges", "orange", 0.5f } }, - { { union_ex(contact_polygons, false) }, { "contact_polygons", "blue", 0.5f } }, - { { union_ex(bridges, false) }, { "bridges", "red", "black", "", scaled(0.1f), 0.5f } } }); + { { { union_ex(offset(layerm->unsupported_bridge_edges, scale_(SUPPORT_MATERIAL_MARGIN), SUPPORT_SURFACES_OFFSET_PARAMETERS)) }, { "unsupported_bridge_edges", "orange", 0.5f } }, + { { union_ex(contact_polygons) }, { "contact_polygons", "blue", 0.5f } }, + { { union_ex(bridges) }, { "bridges", "red", "black", "", scaled(0.1f), 0.5f } } }); #endif /* SLIC3R_DEBUG */ } } @@ -1494,7 +1495,7 @@ static inline std::tuple detect_overhangs( iRun, layer_id, std::find_if(layer.regions().begin(), layer.regions().end(), [layerm](const LayerRegion* other){return other == layerm;}) - layer.regions().begin()), get_extents(diff_polygons)); - Slic3r::ExPolygons expolys = union_ex(diff_polygons, false); + Slic3r::ExPolygons expolys = union_ex(diff_polygons); svg.draw(expolys); } #endif /* SLIC3R_DEBUG */ @@ -1512,7 +1513,7 @@ static inline std::tuple detect_overhangs( iRun, layer_id, std::find_if(layer.regions().begin(), layer.regions().end(), [layerm](const LayerRegion* other){return other == layerm;}) - layer.regions().begin(), layer.print_z), - union_ex(diff_polygons, false)); + union_ex(diff_polygons)); #endif /* SLIC3R_DEBUG */ //FIXME the overhang_polygons are used to construct the support towers as well. @@ -1572,10 +1573,10 @@ static inline std::tuple detect_overhangs( offset(lower_layer_polygons, 0.05f * fw, SUPPORT_SURFACES_OFFSET_PARAMETERS)); #ifdef SLIC3R_DEBUG SVG::export_expolygons(debug_out_path("support-top-contacts-enforcers-run%d-layer%d-z%f.svg", iRun, layer_id, layer.print_z), - { { layer.lslices, { "layer.lslices", "gray", 0.2f } }, - { { union_ex(lower_layer_polygons, false) }, { "lower_layer_polygons", "green", 0.5f } }, - { enforcers_united, { "enforcers", "blue", 0.5f } }, - { { union_ex(enforcer_polygons, true) }, { "new_contacts", "red", "black", "", scaled(0.1f), 0.5f } } }); + { { layer.lslices, { "layer.lslices", "gray", 0.2f } }, + { { union_ex(lower_layer_polygons) }, { "lower_layer_polygons", "green", 0.5f } }, + { enforcers_united, { "enforcers", "blue", 0.5f } }, + { { union_safety_offset_ex(enforcer_polygons) }, { "new_contacts", "red", "black", "", scaled(0.1f), 0.5f } } }); #endif /* SLIC3R_DEBUG */ polygons_append(overhang_polygons, enforcer_polygons); polygons_append(contact_polygons, diff(enforcer_polygons, slices_margin.all_polygons.empty() ? slices_margin.polygons : slices_margin.all_polygons)); @@ -1739,18 +1740,18 @@ static inline void fill_contact_layer( ); #ifdef SLIC3R_DEBUG SVG::export_expolygons(debug_out_path("support-top-contacts-final0-run%d-layer%d-z%f.svg", iRun, layer_id, layer.print_z), - { { { union_ex(lower_layer_polygons, false) }, { "lower_layer_polygons", "gray", 0.2f } }, - { { union_ex(*new_layer.contact_polygons, false) }, { "new_layer.contact_polygons", "yellow", 0.5f } }, - { { union_ex(slices_margin.polygons, false) }, { "slices_margin_cached", "blue", 0.5f } }, - { { union_ex(dense_interface_polygons, false) }, { "dense_interface_polygons", "green", 0.5f } }, - { { union_ex(new_layer.polygons, true) }, { "new_layer.polygons", "red", "black", "", scaled(0.1f), 0.5f } } }); + { { { union_ex(lower_layer_polygons) }, { "lower_layer_polygons", "gray", 0.2f } }, + { { union_ex(*new_layer.contact_polygons) }, { "new_layer.contact_polygons", "yellow", 0.5f } }, + { { union_ex(slices_margin.polygons) }, { "slices_margin_cached", "blue", 0.5f } }, + { { union_ex(dense_interface_polygons) }, { "dense_interface_polygons", "green", 0.5f } }, + { { union_safety_offset_ex(new_layer.polygons) }, { "new_layer.polygons", "red", "black", "", scaled(0.1f), 0.5f } } }); //support_grid_pattern.serialize(debug_out_path("support-top-contacts-final-run%d-layer%d-z%f.bin", iRun, layer_id, layer.print_z)); SVG::export_expolygons(debug_out_path("support-top-contacts-final0-run%d-layer%d-z%f.svg", iRun, layer_id, layer.print_z), - { { { union_ex(lower_layer_polygons, false) }, { "lower_layer_polygons", "gray", 0.2f } }, - { { union_ex(*new_layer.contact_polygons, false) }, { "new_layer.contact_polygons", "yellow", 0.5f } }, - { { union_ex(contact_polygons, false) }, { "contact_polygons", "blue", 0.5f } }, - { { union_ex(dense_interface_polygons, false) }, { "dense_interface_polygons", "green", 0.5f } }, - { { union_ex(new_layer.polygons, true) }, { "new_layer.polygons", "red", "black", "", scaled(0.1f), 0.5f } } }); + { { { union_ex(lower_layer_polygons) }, { "lower_layer_polygons", "gray", 0.2f } }, + { { union_ex(*new_layer.contact_polygons) }, { "new_layer.contact_polygons", "yellow", 0.5f } }, + { { union_ex(contact_polygons) }, { "contact_polygons", "blue", 0.5f } }, + { { union_ex(dense_interface_polygons) }, { "dense_interface_polygons", "green", 0.5f } }, + { { union_safety_offset_ex(new_layer.polygons) }, { "new_layer.polygons", "red", "black", "", scaled(0.1f), 0.5f } } }); #endif /* SLIC3R_DEBUG */ } } @@ -1796,11 +1797,11 @@ static inline void fill_contact_layer( #ifdef SLIC3R_DEBUG SVG::export_expolygons(debug_out_path("support-top-contacts-final0-run%d-layer%d-z%f.svg", iRun, layer_id, layer.print_z), - { { { union_ex(lower_layer_polygons, false) }, { "lower_layer_polygons", "gray", 0.2f } }, - { { union_ex(*new_layer.contact_polygons, false) }, { "new_layer.contact_polygons", "yellow", 0.5f } }, - { { union_ex(contact_polygons, false) }, { "contact_polygons", "blue", 0.5f } }, - { { union_ex(overhang_polygons, false) }, { "overhang_polygons", "green", 0.5f } }, - { { union_ex(new_layer.polygons, true) }, { "new_layer.polygons", "red", "black", "", scaled(0.1f), 0.5f } } }); + { { { union_ex(lower_layer_polygons) }, { "lower_layer_polygons", "gray", 0.2f } }, + { { union_ex(*new_layer.contact_polygons) }, { "new_layer.contact_polygons", "yellow", 0.5f } }, + { { union_ex(contact_polygons) }, { "contact_polygons", "blue", 0.5f } }, + { { union_ex(overhang_polygons) }, { "overhang_polygons", "green", 0.5f } }, + { { union_safety_offset_ex(new_layer.polygons) }, { "new_layer.polygons", "red", "black", "", scaled(0.1f), 0.5f } } }); #endif /* SLIC3R_DEBUG */ // Even after the contact layer was expanded into a grid, some of the contact islands may be too tiny to be extruded. @@ -1964,10 +1965,10 @@ static inline PrintObjectSupportMaterial::MyLayer* detect_bottom_contacts( Polygons top = collect_region_slices_by_type(layer, stTop); #ifdef SLIC3R_DEBUG SVG::export_expolygons(debug_out_path("support-bottom-layers-raw-%d-%lf.svg", iRun, layer.print_z), - { { { union_ex(top, false) }, { "top", "blue", 0.5f } }, - { { union_ex(supports_projected, true) }, { "overhangs", "magenta", 0.5f } }, - { layer.lslices, { "layer.lslices", "green", 0.5f } }, - { { union_ex(polygons_new, true) }, { "polygons_new", "red", "black", "", scaled(0.1f), 0.5f } } }); + { { { union_ex(top) }, { "top", "blue", 0.5f } }, + { { union_safety_offset_ex(supports_projected) }, { "overhangs", "magenta", 0.5f } }, + { layer.lslices, { "layer.lslices", "green", 0.5f } }, + { { union_safety_offset_ex(polygons_new) }, { "polygons_new", "red", "black", "", scaled(0.1f), 0.5f } } }); #endif /* SLIC3R_DEBUG */ // Now find whether any projection of the contact surfaces above layer.print_z not yet supported by any @@ -2037,7 +2038,7 @@ static inline PrintObjectSupportMaterial::MyLayer* detect_bottom_contacts( #ifdef SLIC3R_DEBUG Slic3r::SVG::export_expolygons( debug_out_path("support-bottom-contacts-%d-%lf.svg", iRun, layer_new.print_z), - union_ex(layer_new.polygons, false)); + union_ex(layer_new.polygons)); #endif /* SLIC3R_DEBUG */ // Trim the already created base layers above the current layer intersecting with the new bottom contacts layer. @@ -2050,14 +2051,14 @@ static inline PrintObjectSupportMaterial::MyLayer* detect_bottom_contacts( if (! layer_support_areas[layer_id_above].empty()) { #ifdef SLIC3R_DEBUG SVG::export_expolygons(debug_out_path("support-support-areas-raw-before-trimming-%d-with-%f-%lf.svg", iRun, layer.print_z, layer_above.print_z), - { { { union_ex(touching, false) }, { "touching", "blue", 0.5f } }, - { { union_ex(layer_support_areas[layer_id_above], true) }, { "above", "red", "black", "", scaled(0.1f), 0.5f } } }); + { { { union_ex(touching) }, { "touching", "blue", 0.5f } }, + { { union_safety_offset_ex(layer_support_areas[layer_id_above]) }, { "above", "red", "black", "", scaled(0.1f), 0.5f } } }); #endif /* SLIC3R_DEBUG */ layer_support_areas[layer_id_above] = diff(layer_support_areas[layer_id_above], touching); #ifdef SLIC3R_DEBUG Slic3r::SVG::export_expolygons( debug_out_path("support-support-areas-raw-after-trimming-%d-with-%f-%lf.svg", iRun, layer.print_z, layer_above.print_z), - union_ex(layer_support_areas[layer_id_above], false)); + union_ex(layer_support_areas[layer_id_above])); #endif /* SLIC3R_DEBUG */ } } @@ -2080,8 +2081,8 @@ static inline std::pair project_support_to_grid(const Layer #ifdef SLIC3R_DEBUG SVG::export_expolygons(debug_out_path("support-support-areas-%s-raw-%d-%lf.svg", debug_name, iRun, layer.print_z), - { { { union_ex(trimming, false) }, { "trimming", "blue", 0.5f } }, - { { union_ex(overhangs_projection, true) }, { "overhangs_projection", "red", "black", "", scaled(0.1f), 0.5f } } }); + { { { union_ex(trimming) }, { "trimming", "blue", 0.5f } }, + { { union_safety_offset_ex(overhangs_projection) }, { "overhangs_projection", "red", "black", "", scaled(0.1f), 0.5f } } }); #endif /* SLIC3R_DEBUG */ remove_sticks(overhangs_projection); @@ -2089,8 +2090,8 @@ static inline std::pair project_support_to_grid(const Layer #ifdef SLIC3R_DEBUG SVG::export_expolygons(debug_out_path("support-support-areas-%s-raw-cleaned-%d-%lf.svg", debug_name, iRun, layer.print_z), - { { { union_ex(trimming, false) }, { "trimming", "blue", 0.5f } }, - { { union_ex(overhangs_projection, false) }, { "overhangs_projection", "red", "black", "", scaled(0.1f), 0.5f } } }); + { { { union_ex(trimming) }, { "trimming", "blue", 0.5f } }, + { { union_ex(overhangs_projection) }, { "overhangs_projection", "red", "black", "", scaled(0.1f), 0.5f } } }); #endif /* SLIC3R_DEBUG */ SupportGridPattern support_grid_pattern(&overhangs_projection, &trimming, grid_params); @@ -2113,7 +2114,7 @@ static inline std::pair project_support_to_grid(const Layer #ifdef SLIC3R_DEBUG Slic3r::SVG::export_expolygons( debug_out_path("support-layer_support_area-gridded-%s-%d-%lf.svg", debug_name, iRun, layer.print_z), - union_ex(out.first, false)); + union_ex(out.first)); #endif /* SLIC3R_DEBUG */ }); @@ -2131,13 +2132,13 @@ static inline std::pair project_support_to_grid(const Layer #ifdef SLIC3R_DEBUG Slic3r::SVG::export_expolygons( debug_out_path("support-projection_new-gridded-%d-%lf.svg", iRun, layer.print_z), - union_ex(out.second, false)); + union_ex(out.second)); #endif /* SLIC3R_DEBUG */ #ifdef SLIC3R_DEBUG SVG::export_expolygons(debug_out_path("support-projection_new-gridded-%d-%lf.svg", iRun, layer.print_z), - { { { union_ex(trimming, false) }, { "trimming", "gray", 0.5f } }, - { { union_ex(overhangs_projection, true) }, { "overhangs_projection", "blue", 0.5f } }, - { { union_ex(out.second, true) }, { "projection_new", "red", "black", "", scaled(0.1f), 0.5f } } }); + { { { union_ex(trimming) }, { "trimming", "gray", 0.5f } }, + { { union_safety_offset_ex(overhangs_projection) }, { "overhangs_projection", "blue", 0.5f } }, + { { union_safety_offset_ex(out.second) }, { "projection_new", "red", "black", "", scaled(0.1f), 0.5f } } }); #endif /* SLIC3R_DEBUG */ }); @@ -2667,10 +2668,10 @@ void PrintObjectSupportMaterial::generate_base_layers( BoundingBox bbox = get_extents(polygons_new); bbox.merge(get_extents(polygons_trimming)); ::Slic3r::SVG svg(debug_out_path("support-intermediate-layers-raw-%d-%lf.svg", iRun, layer_intermediate.print_z), bbox); - svg.draw(union_ex(polygons_new, false), "blue", 0.5f); - svg.draw(to_polylines(polygons_new), "blue"); - svg.draw(union_ex(polygons_trimming, true), "red", 0.5f); - svg.draw(to_polylines(polygons_trimming), "red"); + svg.draw(union_ex(polygons_new), "blue", 0.5f); + svg.draw(to_polylines(polygons_new), "blue"); + svg.draw(union_safety_offset_ex(polygons_trimming), "red", 0.5f); + svg.draw(to_polylines(polygons_trimming), "red"); } #endif /* SLIC3R_DEBUG */ @@ -2706,7 +2707,7 @@ void PrintObjectSupportMaterial::generate_base_layers( for (MyLayersPtr::const_iterator it = intermediate_layers.begin(); it != intermediate_layers.end(); ++it) ::Slic3r::SVG::export_expolygons( debug_out_path("support-intermediate-layers-untrimmed-%d-%lf.svg", iRun, (*it)->print_z), - union_ex((*it)->polygons, false)); + union_ex((*it)->polygons)); ++ iRun; #endif /* SLIC3R_DEBUG */ diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index 1b02e0331..a01e63166 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -58,6 +58,11 @@ void set_data_dir(const std::string &path); // Return a full path to the GUI resource files. const std::string& data_dir(); +// Format an output path for debugging purposes. +// Writes out the output path prefix to the console for the first time the function is called, +// so the user knows where to search for the debugging output. +std::string debug_out_path(const char *name, ...); + // A special type for strings encoded in the local Windows 8-bit code page. // This type is only needed for Perl bindings to relay to Perl that the string is raw, not UTF-8 encoded. typedef std::string local_encoded_string; diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index 8d8d15df9..a29436189 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -65,18 +65,6 @@ static constexpr double EXTERNAL_INFILL_MARGIN = 3.; #define SCALED_EPSILON scale_(EPSILON) -#define SLIC3R_DEBUG_OUT_PATH_PREFIX "out/" - -inline std::string debug_out_path(const char *name, ...) -{ - char buffer[2048]; - va_list args; - va_start(args, name); - std::vsprintf(buffer, name, args); - va_end(args); - return std::string(SLIC3R_DEBUG_OUT_PATH_PREFIX) + std::string(buffer); -} - #ifndef UNUSED #define UNUSED(x) (void)(x) #endif /* UNUSED */ diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp index 29f955e92..78125079a 100644 --- a/src/libslic3r/utils.cpp +++ b/src/libslic3r/utils.cpp @@ -207,6 +207,23 @@ std::string custom_shapes_dir() return (boost::filesystem::path(g_data_dir) / "shapes").string(); } +static std::atomic debug_out_path_called(false); + +std::string debug_out_path(const char *name, ...) +{ + static constexpr const char *SLIC3R_DEBUG_OUT_PATH_PREFIX = "out/"; + if (! debug_out_path_called.exchange(true)) { + std::string path = boost::filesystem::system_complete(SLIC3R_DEBUG_OUT_PATH_PREFIX).string(); + printf("Debugging output files will be written to %s\n", path.c_str()); + } + char buffer[2048]; + va_list args; + va_start(args, name); + std::vsprintf(buffer, name, args); + va_end(args); + return std::string(SLIC3R_DEBUG_OUT_PATH_PREFIX) + std::string(buffer); +} + #ifdef _WIN32 // The following helpers are borrowed from the LLVM project https://github.com/llvm namespace WindowsSupport From fbe46959589a0b51df0584ffc83e1a1d7222a159 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 27 Aug 2021 11:30:37 +0200 Subject: [PATCH 20/60] Slight optimization of GLGizmoSimplify::process(): Moved a static variable from inside a lambda outside as the static inner variable initialization & access has to be made thread safe. --- src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp index d4e14c6f4..b9e5d111b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSimplify.cpp @@ -283,11 +283,11 @@ void GLGizmoSimplify::process() } }; - std::function statusfn = [this](int percent) { + int64_t last = 0; + std::function statusfn = [this, &last](int percent) { m_progress = percent; // check max 4fps - static int64_t last = 0; int64_t now = m_parent.timestamp_now(); if ((now - last) < 250) return; last = now; From 9c4eeeaa189d5051c3e8e9acc98f91765e0e6068 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 27 Aug 2021 11:41:34 +0200 Subject: [PATCH 21/60] Tech ENABLE_SEAMS_USING_INSTANCED_MODELS merged into tech ENABLE_SEAMS_USING_MODELS --- src/libslic3r/Technologies.hpp | 2 - src/slic3r/GUI/GCodeViewer.cpp | 135 +++------------------------- src/slic3r/GUI/GCodeViewer.hpp | 43 ++------- src/slic3r/GUI/GLModel.cpp | 4 +- src/slic3r/GUI/GLModel.hpp | 4 +- src/slic3r/GUI/GLShadersManager.cpp | 8 +- 6 files changed, 30 insertions(+), 166 deletions(-) diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index f11ad4a17..e03887d26 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -51,8 +51,6 @@ #define ENABLE_RETRACT_ACCELERATION (1 && ENABLE_2_4_0_ALPHA0) // Enable rendering seams (and other options) in preview using models #define ENABLE_SEAMS_USING_MODELS (1 && ENABLE_2_4_0_ALPHA0) -// Enable rendering seams (and other options) in preview using instanced models -#define ENABLE_SEAMS_USING_INSTANCED_MODELS (1 && ENABLE_SEAMS_USING_MODELS) #endif // _prusaslicer_technologies_h_ diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index c672f9060..382b78ca3 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -95,7 +95,7 @@ void GCodeViewer::VBuffer::reset() count = 0; } -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS void GCodeViewer::InstanceVBuffer::Ranges::reset() { for (Range& range : ranges) { @@ -113,7 +113,7 @@ void GCodeViewer::InstanceVBuffer::reset() buffer.clear(); render_ranges.reset(); } -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS void GCodeViewer::IBuffer::reset() { @@ -159,11 +159,7 @@ bool GCodeViewer::Path::matches(const GCodeProcessor::MoveVertex& move) const #if ENABLE_SEAMS_USING_MODELS void GCodeViewer::TBuffer::Model::reset() { -#if ENABLE_SEAMS_USING_INSTANCED_MODELS instances.reset(); -#else - instances.clear(); -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS } #endif // ENABLE_SEAMS_USING_MODELS @@ -813,11 +809,7 @@ void GCodeViewer::render() #if ENABLE_SEAMS_USING_MODELS if (wxGetApp().is_gl_version_greater_or_equal_to(3, 1)) { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Model; -#if ENABLE_SEAMS_USING_INSTANCED_MODELS buffer.shader = "gouraud_light_instanced"; -#else - buffer.shader = "gouraud_light"; -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS buffer.model.model.init_from(diamond(16)); buffer.model.color = option_color(type); } @@ -870,9 +862,9 @@ void GCodeViewer::render() #if ENABLE_GCODE_VIEWER_STATISTICS m_statistics.reset_opengl(); -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS m_statistics.total_instances_gpu_size = 0; -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS #endif // ENABLE_GCODE_VIEWER_STATISTICS // OpenGL data must be initialized after the glContext has been created. @@ -1444,7 +1436,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) }; #if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_INSTANCED_MODELS // format data into the buffers to be rendered as model auto add_model_instance = [](const GCodeProcessor::MoveVertex& curr, InstanceBuffer& instances, InstanceIdBuffer& instances_ids, size_t move_id) { // append position @@ -1459,16 +1450,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // append id instances_ids.push_back(move_id); }; -#else - auto add_model_instance = [](const GCodeProcessor::MoveVertex& curr, TBuffer::Model::Instances& instances, size_t move_id) { - TBuffer::Model::Instance instance; - instance.position = curr.position; - instance.width = 1.2f * curr.width; - instance.height = 1.2f * curr.height; - instance.s_id = move_id; - instances.emplace_back(instance); - }; -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_SEAMS_USING_MODELS #if ENABLE_GCODE_VIEWER_STATISTICS @@ -1513,10 +1494,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) std::vector vertices(m_buffers.size()); std::vector indices(m_buffers.size()); -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS std::vector instances(m_buffers.size()); std::vector instances_ids(m_buffers.size()); -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS std::vector options_zs; // toolpaths data -> extract vertices from result @@ -1541,10 +1522,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) const unsigned char id = buffer_id(curr.type); TBuffer& t_buffer = m_buffers[id]; MultiVertexBuffer& v_multibuffer = vertices[id]; -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS InstanceBuffer& inst_buffer = instances[id]; InstanceIdBuffer& inst_id_buffer = instances_ids[id]; -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS // ensure there is at least one vertex buffer if (v_multibuffer.empty()) @@ -1571,11 +1552,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) #if ENABLE_SEAMS_USING_MODELS case TBuffer::ERenderPrimitiveType::Model: { -#if ENABLE_SEAMS_USING_INSTANCED_MODELS add_model_instance(curr, inst_buffer, inst_id_buffer, i); -#else - add_model_instance(curr, t_buffer.model.instances, i); -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #if ENABLE_GCODE_VIEWER_STATISTICS ++m_statistics.instances_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -1752,17 +1729,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) } } -#if ENABLE_SEAMS_USING_MODELS -#if !ENABLE_SEAMS_USING_INSTANCED_MODELS - for (size_t i = 0; i < m_buffers.size(); ++i) { - TBuffer& t_buffer = m_buffers[i]; - if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { - t_buffer.model.instances.shrink_to_fit(); - } - } -#endif // !ENABLE_SEAMS_USING_INSTANCED_MODELS -#endif // ENABLE_SEAMS_USING_MODELS - // move the wipe toolpaths half height up to render them on proper position MultiVertexBuffer& wipe_vertices = vertices[buffer_id(EMoveType::Wipe)]; for (VertexBuffer& v_buffer : wipe_vertices) { @@ -1771,15 +1737,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) } } -#if ENABLE_SEAMS_USING_INSTANCED_MODELS // send vertices data to gpu, where needed -#else - // send vertices data to gpu -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS for (size_t i = 0; i < m_buffers.size(); ++i) { TBuffer& t_buffer = m_buffers[i]; #if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_INSTANCED_MODELS if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { const InstanceBuffer& inst_buffer = instances[i]; if (!inst_buffer.empty()) { @@ -1788,9 +1749,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) } } else { -#else - if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Model) { -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_SEAMS_USING_MODELS const MultiVertexBuffer& v_multibuffer = vertices[i]; for (const VertexBuffer& v_buffer : v_multibuffer) { @@ -1827,10 +1785,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // dismiss vertices data, no more needed std::vector().swap(vertices); -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS std::vector().swap(instances); std::vector().swap(instances_ids); -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS // toolpaths data -> extract indices from result // paths may have been filled while extracting vertices, @@ -2217,7 +2175,6 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool #if ENABLE_SEAMS_USING_MODELS if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { -#if ENABLE_SEAMS_USING_INSTANCED_MODELS for (size_t id : buffer.model.instances.s_ids) { if (id < m_layers.get_endpoints_at(m_layers_z_range[0]).first || m_layers.get_endpoints_at(m_layers_z_range[1]).last < id) continue; @@ -2233,23 +2190,6 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool top_layer_endpoints.last = std::max(top_layer_endpoints.last, id); } } -#else - for (const TBuffer::Model::Instance& inst : buffer.model.instances) { - if (inst.s_id < m_layers.get_endpoints_at(m_layers_z_range[0]).first || m_layers.get_endpoints_at(m_layers_z_range[1]).last < inst.s_id) - continue; - - global_endpoints.first = std::min(global_endpoints.first, inst.s_id); - global_endpoints.last = std::max(global_endpoints.last, inst.s_id); - - if (top_layer_only) { - if (inst.s_id < m_layers.get_endpoints_at(m_layers_z_range[1]).first || m_layers.get_endpoints_at(m_layers_z_range[1]).last < inst.s_id) - continue; - - top_layer_endpoints.first = std::min(top_layer_endpoints.first, inst.s_id); - top_layer_endpoints.last = std::max(top_layer_endpoints.last, inst.s_id); - } - } -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS } else { #endif // ENABLE_SEAMS_USING_MODELS @@ -2295,16 +2235,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool sequential_view->current.first = !top_layer_only && keep_sequential_current_first ? std::clamp(sequential_view->current.first, global_endpoints.first, global_endpoints.last) : global_endpoints.first; sequential_view->current.last = keep_sequential_current_last ? std::clamp(sequential_view->current.last, global_endpoints.first, global_endpoints.last) : global_endpoints.last; -#if ENABLE_SEAMS_USING_INSTANCED_MODELS // get the world position from the vertex buffer -#else - // get the world position from gpu -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS bool found = false; for (const TBuffer& buffer : m_buffers) { #if ENABLE_SEAMS_USING_MODELS if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Model) { -#if ENABLE_SEAMS_USING_INSTANCED_MODELS for (size_t i = 0; i < buffer.model.instances.s_ids.size(); ++i) { if (buffer.model.instances.s_ids[i] == m_sequential_view.current.last) { size_t offset = i * buffer.model.instances.instance_size_floats(); @@ -2316,15 +2251,6 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool break; } } -#else - for (const TBuffer::Model::Instance& inst : buffer.model.instances) { - if (inst.s_id == m_sequential_view.current.last) { - sequential_view->current_position = inst.position; - found = true; - break; - } - } -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS } else { #endif // ENABLE_SEAMS_USING_MODELS @@ -2473,7 +2399,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool #endif } -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS // second pass: for buffers using instanced models, update the instances render ranges for (size_t b = 0; b < m_buffers.size(); ++b) { TBuffer& buffer = const_cast(m_buffers[b]); @@ -2513,7 +2439,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool } } } -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS // set sequential data to their final value sequential_view->endpoints = top_layer_only ? top_layer_endpoints : global_endpoints; @@ -2643,13 +2569,9 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool statistics->render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.offsets, size_t); } #if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_INSTANCED_MODELS statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances.buffer, float); statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances.s_ids, size_t); statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances.render_ranges.ranges, InstanceVBuffer::Ranges::Range); -#else - statistics->models_instances_size += SLIC3R_STDVEC_MEMSIZE(buffer.model.instances, TBuffer::Model::Instance); -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_SEAMS_USING_MODELS } statistics->refresh_paths_time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); @@ -2742,11 +2664,8 @@ void GCodeViewer::render_toolpaths() #if ENABLE_SEAMS_USING_MODELS auto render_as_instanced_model = [this] (TBuffer& buffer, GLShaderProgram & shader) { -#if ENABLE_SEAMS_USING_INSTANCED_MODELS for (auto& range : buffer.model.instances.render_ranges.ranges) { if (range.vbo == 0 && range.count > 0) { - std::cout << range.offset * buffer.model.instances.instance_size_bytes() << " + " << range.count * buffer.model.instances.instance_size_bytes() << " = " << buffer.model.instances.buffer.size() * sizeof(float) << "\n"; - glsafe(::glGenBuffers(1, &range.vbo)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, range.vbo)); glsafe(::glBufferData(GL_ARRAY_BUFFER, range.count * buffer.model.instances.instance_size_bytes(), (const void*)&buffer.model.instances.buffer[range.offset * buffer.model.instances.instance_size_floats()], GL_STATIC_DRAW)); @@ -2762,28 +2681,6 @@ void GCodeViewer::render_toolpaths() #endif // ENABLE_GCODE_VIEWER_STATISTICS } } -#else - for (const TBuffer::Model::Instance& inst : buffer.model.instances) { - bool top_layer_only = get_app_config()->get("seq_top_layer_only") == "1"; - bool visible = top_layer_only ? - m_sequential_view.global.first <= inst.s_id && inst.s_id <= m_sequential_view.global.last : - m_sequential_view.current.first <= inst.s_id && inst.s_id <= m_sequential_view.current.last; - - if (visible) { - glsafe(::glPushMatrix()); - glsafe(::glTranslatef(inst.position.x(), inst.position.y(), inst.position.z() - 0.5f * inst.height)); - glsafe(::glScalef(inst.width, inst.width, inst.height)); - Color color = (top_layer_only && m_sequential_view.current.last != m_sequential_view.global.last && inst.s_id < m_sequential_view.endpoints.first) ? - Neutral_Color : buffer.model.color; - buffer.model.model.set_color(-1, color); - buffer.model.model.render(); - glsafe(::glPopMatrix()); -#if ENABLE_GCODE_VIEWER_STATISTICS - ++m_statistics.gl_models_calls_count; -#endif // ENABLE_GCODE_VIEWER_STATISTICS - } - } -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS }; #endif // ENABLE_SEAMS_USING_MODELS @@ -3852,11 +3749,7 @@ void GCodeViewer::render_statistics() add_counter(std::string("Multi GL_TRIANGLES:"), m_statistics.gl_multi_triangles_calls_count); add_counter(std::string("GL_TRIANGLES:"), m_statistics.gl_triangles_calls_count); #if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_INSTANCED_MODELS add_counter(std::string("Instanced models:"), m_statistics.gl_instanced_models_calls_count); -#else - add_counter(std::string("Models:"), m_statistics.gl_models_calls_count); -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_SEAMS_USING_MODELS } @@ -3874,9 +3767,9 @@ void GCodeViewer::render_statistics() if (ImGui::CollapsingHeader("GPU memory")) { add_memory(std::string("Vertices:"), m_statistics.total_vertices_gpu_size); add_memory(std::string("Indices:"), m_statistics.total_indices_gpu_size); -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS add_memory(std::string("Instances:"), m_statistics.total_instances_gpu_size); -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS ImGui::Separator(); add_memory(std::string("Max VBuffer:"), m_statistics.max_vbuffer_gpu_size); add_memory(std::string("Max IBuffer:"), m_statistics.max_ibuffer_gpu_size); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 46f6558dd..429175fe6 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -27,10 +27,10 @@ class GCodeViewer using MultiVertexBuffer = std::vector; using IndexBuffer = std::vector; using MultiIndexBuffer = std::vector; -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS using InstanceBuffer = std::vector; using InstanceIdBuffer = std::vector; -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS static const std::vector Extrusion_Role_Colors; static const std::vector Options_Colors; @@ -104,7 +104,7 @@ class GCodeViewer void reset(); }; -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS // buffer containing instances data used to render a toolpaths using instanced models // instance record format: 5 floats -> position.x|position.y|position.z|width|height // which is sent to the shader as -> vec3 (offset) + vec2 (scales) in GLModel::render_instanced() @@ -143,7 +143,7 @@ class GCodeViewer void reset(); }; -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS // ibo buffer containing indices data (for lines/triangles) used to render a specific toolpath type struct IBuffer @@ -295,24 +295,9 @@ class GCodeViewer #if ENABLE_SEAMS_USING_MODELS struct Model { -#if !ENABLE_SEAMS_USING_INSTANCED_MODELS - struct Instance - { - Vec3f position; - float width; - float height; - size_t s_id; - }; - using Instances = std::vector; -#endif // !ENABLE_SEAMS_USING_INSTANCED_MODELS - GLModel model; Color color; -#if ENABLE_SEAMS_USING_INSTANCED_MODELS InstanceVBuffer instances; -#else - Instances instances; -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS void reset(); }; @@ -377,11 +362,7 @@ class GCodeViewer case ERenderPrimitiveType::Triangle: { return !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; } -#if ENABLE_SEAMS_USING_INSTANCED_MODELS case ERenderPrimitiveType::Model: { return model.model.is_initialized() && !model.instances.buffer.empty(); } -#else - case ERenderPrimitiveType::Model: { return model.model.is_initialized() && !model.instances.empty(); } -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS default: { return false; } } } @@ -538,19 +519,15 @@ class GCodeViewer int64_t gl_multi_triangles_calls_count{ 0 }; int64_t gl_triangles_calls_count{ 0 }; #if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_INSTANCED_MODELS int64_t gl_instanced_models_calls_count{ 0 }; -#else - int64_t gl_models_calls_count{ 0 }; -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_SEAMS_USING_MODELS // memory int64_t results_size{ 0 }; int64_t total_vertices_gpu_size{ 0 }; int64_t total_indices_gpu_size{ 0 }; -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS int64_t total_instances_gpu_size{ 0 }; -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS int64_t max_vbuffer_gpu_size{ 0 }; int64_t max_ibuffer_gpu_size{ 0 }; int64_t paths_size{ 0 }; @@ -591,11 +568,7 @@ class GCodeViewer gl_multi_triangles_calls_count = 0; gl_triangles_calls_count = 0; #if ENABLE_SEAMS_USING_MODELS -#if ENABLE_SEAMS_USING_INSTANCED_MODELS gl_instanced_models_calls_count = 0; -#else - gl_models_calls_count = 0; -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS #endif // ENABLE_SEAMS_USING_MODELS } @@ -603,9 +576,9 @@ class GCodeViewer results_size = 0; total_vertices_gpu_size = 0; total_indices_gpu_size = 0; -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS total_instances_gpu_size = 0; -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS max_vbuffer_gpu_size = 0; max_ibuffer_gpu_size = 0; paths_size = 0; diff --git a/src/slic3r/GUI/GLModel.cpp b/src/slic3r/GUI/GLModel.cpp index ce44c4649..5cddd7fa3 100644 --- a/src/slic3r/GUI/GLModel.cpp +++ b/src/slic3r/GUI/GLModel.cpp @@ -208,7 +208,7 @@ void GLModel::render() const } } -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instances_count) const { if (instances_vbo == 0) @@ -285,7 +285,7 @@ void GLModel::render_instanced(unsigned int instances_vbo, unsigned int instance glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS void GLModel::send_to_gpu(RenderData& data, const std::vector& vertices, const std::vector& indices) { diff --git a/src/slic3r/GUI/GLModel.hpp b/src/slic3r/GUI/GLModel.hpp index 73fb90827..8e0039b08 100644 --- a/src/slic3r/GUI/GLModel.hpp +++ b/src/slic3r/GUI/GLModel.hpp @@ -72,9 +72,9 @@ namespace GUI { void reset(); void render() const; -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS void render_instanced(unsigned int instances_vbo, unsigned int instances_count) const; -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS bool is_initialized() const { return !m_render_data.empty(); } diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index 418fe8d1e..c93f22f46 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -38,17 +38,17 @@ std::pair GLShadersManager::init() // used to render printbed valid &= append_shader("printbed", { "printbed.vs", "printbed.fs" }); // used to render options in gcode preview -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 1)) valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); else { -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS valid &= append_shader("options_110", { "options_110.vs", "options_110.fs" }); if (GUI::wxGetApp().is_glsl_version_greater_or_equal_to(1, 20)) valid &= append_shader("options_120", { "options_120.vs", "options_120.fs" }); -#if ENABLE_SEAMS_USING_INSTANCED_MODELS +#if ENABLE_SEAMS_USING_MODELS } -#endif // ENABLE_SEAMS_USING_INSTANCED_MODELS +#endif // ENABLE_SEAMS_USING_MODELS // used to render extrusion and travel paths as lines in gcode preview valid &= append_shader("toolpaths_lines", { "toolpaths_lines.vs", "toolpaths_lines.fs" }); // used to render objects in 3d editor From 7852ba061c7bbfba6431335305e18b772f3ebd94 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 27 Aug 2021 12:10:25 +0200 Subject: [PATCH 22/60] Slightly reworded the 'Empty layers detected' warning, it mentions the layers between which the problem occurs, not just the upper one (which may be unclear). --- src/libslic3r/GCode.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 254f1d4fd..85e6f810b 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -13,6 +13,7 @@ #include "ClipperUtils.hpp" #include "libslic3r.h" #include "LocalesUtils.hpp" +#include "libslic3r/format.hpp" #include #include @@ -512,7 +513,8 @@ std::vector GCode::collect_layers_to_print(const PrintObjec bool has_extrusions = (layer_to_print.object_layer && layer_to_print.object_layer->has_extrusions()) || (layer_to_print.support_layer && layer_to_print.support_layer->has_extrusions()); - // Check that there are extrusions on the very first layer. + // Check that there are extrusions on the very first layer. The case with empty + // first layer may result in skirt/brim in the air and maybe other issues. if (layers_to_print.size() == 1u) { if (!has_extrusions) throw Slic3r::SlicingError(_(L("There is an object with no extrusions in the first layer.")) + "\n" + @@ -534,11 +536,12 @@ std::vector GCode::collect_layers_to_print(const PrintObjec if (has_extrusions && layer_to_print.print_z() > maximal_print_z + 2. * EPSILON) { const_cast(object.print())->active_step_add_warning(PrintStateBase::WarningLevel::CRITICAL, - _(L("Empty layers detected. Make sure the object is printable.")) + "\n" + - _(L("Object name")) + ": " + object.model_object()->name + "\n" + _(L("Print z")) + ": " + - std::to_string(layers_to_print.back().print_z()) + "\n\n" + _(L("This is " - "usually caused by negligibly small extrusions or by a faulty model. Try to repair " - "the model or change its orientation on the bed."))); + Slic3r::format(_(L("Empty layer detected between heights %1% and %2%. Make sure the object is printable.")), + (last_extrusion_layer ? last_extrusion_layer->print_z() : 0.), + layers_to_print.back().print_z()) + + "\n" + Slic3r::format(_(L("Object name: %1%")), object.model_object()->name) + "\n\n" + + _(L("This is usually caused by negligibly small extrusions or by a faulty model. " + "Try to repair the model or change its orientation on the bed."))); } // Remember last layer with extrusions. From 2844bee60bdb3aa6b84d0b251ba635ebc811f6d3 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 27 Aug 2021 14:01:29 +0200 Subject: [PATCH 23/60] Added missing include (gcc 8.4) --- src/libslic3r/utils.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp index 78125079a..c330f34b2 100644 --- a/src/libslic3r/utils.cpp +++ b/src/libslic3r/utils.cpp @@ -1,6 +1,7 @@ #include "Utils.hpp" #include "I18N.hpp" +#include #include #include #include From 03fce23570bf6a276022639f19fe5964c01b7cb5 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 27 Aug 2021 15:02:43 +0200 Subject: [PATCH 24/60] Fixed Perl bindings --- xs/xsp/XS.xsp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/xs/xsp/XS.xsp b/xs/xsp/XS.xsp index 083d21d38..68ea282bc 100644 --- a/xs/xsp/XS.xsp +++ b/xs/xsp/XS.xsp @@ -23,12 +23,6 @@ BUILD() RETVAL = newSVpv(SLIC3R_BUILD_ID, 0); OUTPUT: RETVAL -SV* -DEBUG_OUT_PATH_PREFIX() - CODE: - RETVAL = newSVpv(SLIC3R_DEBUG_OUT_PATH_PREFIX, 0); - OUTPUT: RETVAL - SV* FORK_NAME() CODE: From 306bd0a1988a6753b8c81b771bd3319104b9cd88 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 27 Aug 2021 15:04:25 +0200 Subject: [PATCH 25/60] Fixed leakage of paint-on supports through thin objects. This is a bug introduced during 2.4.0 refactoring. Fixes To much support #6067 --- src/libslic3r/SupportMaterial.cpp | 46 +++++++++++++++++++------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index c9794a6c8..2e4a47954 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -1417,13 +1417,35 @@ static inline std::tuple detect_overhangs( // Generate overhang / contact_polygons for non-raft layers. const Layer &lower_layer = *layer.lower_layer; const bool has_enforcer = ! annotations.enforcers_layers.empty() && ! annotations.enforcers_layers[layer_id].empty(); - float fw = 0; + + // Cache support trimming polygons derived from lower layer polygons, possible merged with "on build plate only" trimming polygons. + auto slices_margin_update = + [&slices_margin, &lower_layer, &lower_layer_polygons, buildplate_only, has_enforcer, &annotations, layer_id] + (float slices_margin_offset, float no_interface_offset) { + if (slices_margin.offset != slices_margin_offset) { + slices_margin.offset = slices_margin_offset; + slices_margin.polygons = (slices_margin_offset == 0.f) ? + lower_layer_polygons : + offset2(lower_layer.lslices, -no_interface_offset * 0.5f, slices_margin_offset + no_interface_offset * 0.5f, SUPPORT_SURFACES_OFFSET_PARAMETERS); + if (buildplate_only && !annotations.buildplate_covered[layer_id].empty()) { + if (has_enforcer) + // Make a backup of trimming polygons before enforcing "on build plate only". + slices_margin.all_polygons = slices_margin.polygons; + // Trim the inflated contact surfaces by the top surfaces as well. + slices_margin.polygons = union_(slices_margin.polygons, annotations.buildplate_covered[layer_id]); + } + } + }; + + float fw = 0; + float lower_layer_offset = 0; + float no_interface_offset = 0; for (LayerRegion *layerm : layer.regions()) { // Extrusion width accounts for the roundings of the extrudates. // It is the maximum widh of the extrudate. fw = float(layerm->flow(frExternalPerimeter).scaled_width()); no_interface_offset = (no_interface_offset == 0.f) ? fw : std::min(no_interface_offset, fw); - float lower_layer_offset = + lower_layer_offset = (layer_id < (size_t)object_config.support_material_enforce_layers.value) ? // Enforce a full possible support, ignore the overhang angle. 0.f : @@ -1530,20 +1552,7 @@ static inline std::tuple detect_overhangs( //FIXME one should trim with the layer span colliding with the support layer, this layer // may be lower than lower_layer, so the support area needed may need to be actually bigger! // For the same reason, the non-bridging support area may be smaller than the bridging support area! - float slices_margin_offset = std::min(lower_layer_offset, float(scale_(gap_xy))); - if (slices_margin.offset != slices_margin_offset) { - slices_margin.offset = slices_margin_offset; - slices_margin.polygons = (slices_margin_offset == 0.f) ? - lower_layer_polygons : - offset2(lower_layer.lslices, - no_interface_offset * 0.5f, slices_margin_offset + no_interface_offset * 0.5f, SUPPORT_SURFACES_OFFSET_PARAMETERS); - if (buildplate_only && ! annotations.buildplate_covered[layer_id].empty()) { - if (has_enforcer) - // Make a backup of trimming polygons before enforcing "on build plate only". - slices_margin.all_polygons = slices_margin.polygons; - // Trim the inflated contact surfaces by the top surfaces as well. - slices_margin.polygons = union_(slices_margin.polygons, annotations.buildplate_covered[layer_id]); - } - } + slices_margin_update(std::min(lower_layer_offset, float(scale_(gap_xy))), no_interface_offset); // Offset the contact polygons outside. #if 0 for (size_t i = 0; i < NUM_MARGIN_STEPS; ++ i) { @@ -1579,6 +1588,7 @@ static inline std::tuple detect_overhangs( { { union_safety_offset_ex(enforcer_polygons) }, { "new_contacts", "red", "black", "", scaled(0.1f), 0.5f } } }); #endif /* SLIC3R_DEBUG */ polygons_append(overhang_polygons, enforcer_polygons); + slices_margin_update(std::min(lower_layer_offset, float(scale_(gap_xy))), no_interface_offset); polygons_append(contact_polygons, diff(enforcer_polygons, slices_margin.all_polygons.empty() ? slices_margin.polygons : slices_margin.all_polygons)); } } @@ -1739,14 +1749,14 @@ static inline void fill_contact_layer( #endif // SLIC3R_DEBUG ); #ifdef SLIC3R_DEBUG - SVG::export_expolygons(debug_out_path("support-top-contacts-final0-run%d-layer%d-z%f.svg", iRun, layer_id, layer.print_z), + SVG::export_expolygons(debug_out_path("support-top-contacts-final1-run%d-layer%d-z%f.svg", iRun, layer_id, layer.print_z), { { { union_ex(lower_layer_polygons) }, { "lower_layer_polygons", "gray", 0.2f } }, { { union_ex(*new_layer.contact_polygons) }, { "new_layer.contact_polygons", "yellow", 0.5f } }, { { union_ex(slices_margin.polygons) }, { "slices_margin_cached", "blue", 0.5f } }, { { union_ex(dense_interface_polygons) }, { "dense_interface_polygons", "green", 0.5f } }, { { union_safety_offset_ex(new_layer.polygons) }, { "new_layer.polygons", "red", "black", "", scaled(0.1f), 0.5f } } }); //support_grid_pattern.serialize(debug_out_path("support-top-contacts-final-run%d-layer%d-z%f.bin", iRun, layer_id, layer.print_z)); - SVG::export_expolygons(debug_out_path("support-top-contacts-final0-run%d-layer%d-z%f.svg", iRun, layer_id, layer.print_z), + SVG::export_expolygons(debug_out_path("support-top-contacts-final2-run%d-layer%d-z%f.svg", iRun, layer_id, layer.print_z), { { { union_ex(lower_layer_polygons) }, { "lower_layer_polygons", "gray", 0.2f } }, { { union_ex(*new_layer.contact_polygons) }, { "new_layer.contact_polygons", "yellow", 0.5f } }, { { union_ex(contact_polygons) }, { "contact_polygons", "blue", 0.5f } }, From 8dfc0422a878c5e44d4233c6ce522c77a0c3280f Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 27 Aug 2021 15:05:08 +0200 Subject: [PATCH 26/60] Faster and hopefully more reliable projection of paint-on support blockers and enforcers on a sliced mesh. --- src/libslic3r/PrintObject.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index ee09e0f5b..d8d26baa6 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -2294,9 +2294,13 @@ void PrintObject::project_and_append_custom_facets( ? mv->seam_facets.get_facets_strict(*mv, type) : mv->supported_facets.get_facets_strict(*mv, type); if (! custom_facets.indices.empty()) +#if 0 project_triangles_to_slabs(this->layers(), custom_facets, (this->trafo_centered() * mv->get_matrix()).cast(), seam, out); +#else + slice_mesh_slabs(custom_facets, zs_from_layers(this->layers()), this->trafo_centered() * mv->get_matrix(), nullptr, &out, [](){}); +#endif } } From 7bd14bfaf7fef96719a37e5d632c1f09cfebf348 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Fri, 27 Aug 2021 15:23:27 +0200 Subject: [PATCH 27/60] ENABLE_SEAMS_USING_MODELS -> Fixed instances when horizontal slider is enabled for top layer only --- src/slic3r/GUI/GCodeViewer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 382b78ca3..9ac0536a4 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2421,7 +2421,10 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool if (has_second_range) { if (id <= m_sequential_view.endpoints.first) { ++buffer.model.instances.render_ranges.ranges.front().offset; - ++buffer.model.instances.render_ranges.ranges.back().count; + if (id <= m_sequential_view.current.first) + ++buffer.model.instances.render_ranges.ranges.back().offset; + else + ++buffer.model.instances.render_ranges.ranges.back().count; } else if (id <= m_sequential_view.current.last) ++buffer.model.instances.render_ranges.ranges.front().count; From d9f2fd7501274141b55fad7f5f4a982e7286d7d3 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 27 Aug 2021 19:46:44 +0200 Subject: [PATCH 28/60] Fixed shifted clippimg plane triangulation on scaled meshes, fighting z-fighting has to be done in world coords. --- src/slic3r/GUI/MeshUtils.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/MeshUtils.cpp b/src/slic3r/GUI/MeshUtils.cpp index ba83bdbff..75232c930 100644 --- a/src/slic3r/GUI/MeshUtils.cpp +++ b/src/slic3r/GUI/MeshUtils.cpp @@ -106,7 +106,6 @@ void MeshClipper::recalculate_triangles() Transform3d tr = Transform3d::Identity(); tr.rotate(q); tr = m_trafo.get_matrix() * tr; - height_mesh += 0.001f; // to avoid z-fighting if (m_limiting_plane != ClippingPlane::ClipsNothing()) { @@ -165,6 +164,8 @@ void MeshClipper::recalculate_triangles() m_triangles2d = triangulate_expolygons_2f(expolys, m_trafo.get_matrix().matrix().determinant() < 0.); + tr.pretranslate(0.001 * m_plane.get_normal().normalized()); // to avoid z-fighting + m_vertex_array.release_geometry(); for (auto it=m_triangles2d.cbegin(); it != m_triangles2d.cend(); it=it+3) { m_vertex_array.push_geometry(tr * Vec3d((*(it+0))(0), (*(it+0))(1), height_mesh), up); From 1c76df89eaf9dcbad50601a8a8aabd9b6a7e2f84 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Fri, 27 Aug 2021 21:04:11 +0200 Subject: [PATCH 29/60] Fix of paint on supports don't work for object that has been scaled up #6718 The triangle-ray intersection function used a hard coded epsilon, which did not work for triangle meshes, that were either too small or too large. Newly the epsilon may be provided to the AABBTreeIndirect search functions externally and IndexedMesh calculates a suitable epsilon on demand from an average triangle mesh edge length. --- src/libslic3r/AABBTreeIndirect.hpp | 125 ++++++++++++++++++++--------- src/libslic3r/SLA/IndexedMesh.cpp | 26 +++--- src/libslic3r/SLA/IndexedMesh.hpp | 8 +- src/libslic3r/TriangleMesh.cpp | 15 ++++ src/libslic3r/TriangleMesh.hpp | 1 + src/slic3r/GUI/MeshUtils.hpp | 2 +- 6 files changed, 127 insertions(+), 50 deletions(-) diff --git a/src/libslic3r/AABBTreeIndirect.hpp b/src/libslic3r/AABBTreeIndirect.hpp index 76aa36194..217166f8c 100644 --- a/src/libslic3r/AABBTreeIndirect.hpp +++ b/src/libslic3r/AABBTreeIndirect.hpp @@ -15,11 +15,6 @@ #include "Utils.hpp" // for next_highest_power_of_2() -extern "C" -{ -// Ray-Triangle Intersection Test Routines by Tomas Moller, May 2000 -#include -} // Definition of the ray intersection hit structure. #include @@ -231,6 +226,9 @@ namespace detail { const VectorType origin; const VectorType dir; const VectorType invdir; + + // epsilon for ray-triangle intersection, see intersect_triangle1() + const double eps; }; template @@ -283,44 +281,91 @@ namespace detail { return tmin < t1 && tmax > t0; } + // The following intersect_triangle() is derived from raytri.c routine intersect_triangle1() + // Ray-Triangle Intersection Test Routines + // Different optimizations of my and Ben Trumbore's + // code from journals of graphics tools (JGT) + // http://www.acm.org/jgt/ + // by Tomas Moller, May 2000 template - std::enable_if_t::value && std::is_same::value, bool> - intersect_triangle(const V &origin, const V &dir, const W &v0, const W &v1, const W &v2, double &t, double &u, double &v) { - return intersect_triangle1(const_cast(origin.data()), const_cast(dir.data()), - const_cast(v0.data()), const_cast(v1.data()), const_cast(v2.data()), - &t, &u, &v); + std::enable_if_t::value&& std::is_same::value, bool> + intersect_triangle(const V &orig, const V &dir, const W &vert0, const W &vert1, const W &vert2, double &t, double &u, double &v, double eps) + { + // find vectors for two edges sharing vert0 + const V edge1 = vert1 - vert0; + const V edge2 = vert2 - vert0; + // begin calculating determinant - also used to calculate U parameter + const V pvec = dir.cross(edge2); + // if determinant is near zero, ray lies in plane of triangle + const double det = edge1.dot(pvec); + V qvec; + + if (det > eps) { + // calculate distance from vert0 to ray origin + V tvec = orig - vert0; + // calculate U parameter and test bounds + u = tvec.dot(pvec); + if (u < 0.0 || u > det) + return false; + // prepare to test V parameter + qvec = tvec.cross(edge1); + // calculate V parameter and test bounds + v = dir.dot(qvec); + if (v < 0.0 || u + v > det) + return false; + } else if (det < -eps) { + // calculate distance from vert0 to ray origin + V tvec = orig - vert0; + // calculate U parameter and test bounds + u = tvec.dot(pvec); + if (u > 0.0 || u < det) + return false; + // prepare to test V parameter + qvec = tvec.cross(edge1); + // calculate V parameter and test bounds + v = dir.dot(qvec); + if (v > 0.0 || u + v < det) + return false; + } else + // ray is parallel to the plane of the triangle + return false; + + double inv_det = 1.0 / det; + // calculate t, ray intersects triangle + t = edge2.dot(qvec) * inv_det; + u *= inv_det; + v *= inv_det; + return true; } template std::enable_if_t::value && !std::is_same::value, bool> - intersect_triangle(const V &origin, const V &dir, const W &v0, const W &v1, const W &v2, double &t, double &u, double &v) { - using Vector = Eigen::Matrix; - Vector w0 = v0.template cast(); - Vector w1 = v1.template cast(); - Vector w2 = v2.template cast(); - return intersect_triangle1(const_cast(origin.data()), const_cast(dir.data()), - w0.data(), w1.data(), w2.data(), &t, &u, &v); + intersect_triangle(const V &origin, const V &dir, const W &v0, const W &v1, const W &v2, double &t, double &u, double &v, double eps) { + return intersect_triangle(origin, dir, v0.template cast(), v1.template cast(), v2.template cast(), t, u, v, eps); } template std::enable_if_t::value && std::is_same::value, bool> - intersect_triangle(const V &origin, const V &dir, const W &v0, const W &v1, const W &v2, double &t, double &u, double &v) { - using Vector = Eigen::Matrix; - Vector o = origin.template cast(); - Vector d = dir.template cast(); - return intersect_triangle1(o.data(), d.data(), const_cast(v0.data()), const_cast(v1.data()), const_cast(v2.data()), &t, &u, &v); + intersect_triangle(const V &origin, const V &dir, const W &v0, const W &v1, const W &v2, double &t, double &u, double &v, double eps) { + return intersect_triangle(origin.template cast(), dir.template cast(), v0, v1, v2, t, u, v, eps); } template std::enable_if_t::value && ! std::is_same::value, bool> - intersect_triangle(const V &origin, const V &dir, const W &v0, const W &v1, const W &v2, double &t, double &u, double &v) { - using Vector = Eigen::Matrix; - Vector o = origin.template cast(); - Vector d = dir.template cast(); - Vector w0 = v0.template cast(); - Vector w1 = v1.template cast(); - Vector w2 = v2.template cast(); - return intersect_triangle1(o.data(), d.data(), w0.data(), w1.data(), w2.data(), &t, &u, &v); + intersect_triangle(const V &origin, const V &dir, const W &v0, const W &v1, const W &v2, double &t, double &u, double &v, double eps) { + return intersect_triangle(origin.template cast(), dir.template cast(), v0.template cast(), v1.template cast(), v2.template cast(), t, u, v, eps); + } + + template + double intersect_triangle_epsilon(const Tree &tree) { + double eps = 0.000001; + if (! tree.empty()) { + const typename Tree::BoundingBox &bbox = tree.nodes().front().bbox; + double l = (bbox.max() - bbox.min()).cwiseMax(); + if (l > 0) + eps /= (l * l); + } + return eps; } template @@ -343,7 +388,7 @@ namespace detail { if (intersect_triangle( ray_intersector.origin, ray_intersector.dir, ray_intersector.vertices[face(0)], ray_intersector.vertices[face(1)], ray_intersector.vertices[face(2)], - t, u, v) + t, u, v, ray_intersector.eps) && t > 0.) { hit = igl::Hit { int(node.idx), -1, float(u), float(v), float(t) }; return true; @@ -388,7 +433,7 @@ namespace detail { if (intersect_triangle( ray_intersector.origin, ray_intersector.dir, ray_intersector.vertices[face(0)], ray_intersector.vertices[face(1)], ray_intersector.vertices[face(2)], - t, u, v) + t, u, v, ray_intersector.eps) && t > 0.) { ray_intersector.hits.emplace_back(igl::Hit{ int(node.idx), -1, float(u), float(v), float(t) }); } @@ -623,12 +668,15 @@ inline bool intersect_ray_first_hit( // Direction of the ray. const VectorType &dir, // First intersection of the ray with the indexed triangle set. - igl::Hit &hit) + igl::Hit &hit, + // Epsilon for the ray-triangle intersection, it should be proportional to an average triangle edge length. + const double eps = 0.000001) { using Scalar = typename VectorType::Scalar; - auto ray_intersector = detail::RayIntersector { + auto ray_intersector = detail::RayIntersector { vertices, faces, tree, - origin, dir, VectorType(dir.cwiseInverse()) + origin, dir, VectorType(dir.cwiseInverse()), + eps }; return ! tree.empty() && detail::intersect_ray_recursive_first_hit( ray_intersector, size_t(0), std::numeric_limits::infinity(), hit); @@ -652,11 +700,14 @@ inline bool intersect_ray_all_hits( // Direction of the ray. const VectorType &dir, // All intersections of the ray with the indexed triangle set, sorted by parameter t. - std::vector &hits) + std::vector &hits, + // Epsilon for the ray-triangle intersection, it should be proportional to an average triangle edge length. + const double eps = 0.000001) { auto ray_intersector = detail::RayIntersectorHits { { vertices, faces, {tree}, - origin, dir, VectorType(dir.cwiseInverse()) } + origin, dir, VectorType(dir.cwiseInverse()), + eps } }; if (! tree.empty()) { ray_intersector.hits.reserve(8); diff --git a/src/libslic3r/SLA/IndexedMesh.cpp b/src/libslic3r/SLA/IndexedMesh.cpp index 887ef1555..07c4203ab 100644 --- a/src/libslic3r/SLA/IndexedMesh.cpp +++ b/src/libslic3r/SLA/IndexedMesh.cpp @@ -17,10 +17,18 @@ namespace sla { class IndexedMesh::AABBImpl { private: AABBTreeIndirect::Tree3f m_tree; + double m_triangle_ray_epsilon; public: - void init(const indexed_triangle_set &its) + void init(const indexed_triangle_set &its, bool calculate_epsilon) { + m_triangle_ray_epsilon = 0.000001; + if (calculate_epsilon) { + // Calculate epsilon from average triangle edge length. + double l = its_average_edge_length(its); + if (l > 0) + m_triangle_ray_epsilon = 0.000001 * l * l; + } m_tree = AABBTreeIndirect::build_aabb_tree_over_indexed_triangle_set( its.vertices, its.indices); } @@ -31,7 +39,7 @@ public: igl::Hit & hit) { AABBTreeIndirect::intersect_ray_first_hit(its.vertices, its.indices, - m_tree, s, dir, hit); + m_tree, s, dir, hit, m_triangle_ray_epsilon); } void intersect_ray(const indexed_triangle_set &its, @@ -40,7 +48,7 @@ public: std::vector & hits) { AABBTreeIndirect::intersect_ray_all_hits(its.vertices, its.indices, - m_tree, s, dir, hits); + m_tree, s, dir, hits, m_triangle_ray_epsilon); } double squared_distance(const indexed_triangle_set & its, @@ -60,25 +68,25 @@ public: } }; -template void IndexedMesh::init(const M &mesh) +template void IndexedMesh::init(const M &mesh, bool calculate_epsilon) { BoundingBoxf3 bb = bounding_box(mesh); m_ground_level += bb.min(Z); // Build the AABB accelaration tree - m_aabb->init(*m_tm); + m_aabb->init(*m_tm, calculate_epsilon); } -IndexedMesh::IndexedMesh(const indexed_triangle_set& tmesh) +IndexedMesh::IndexedMesh(const indexed_triangle_set& tmesh, bool calculate_epsilon) : m_aabb(new AABBImpl()), m_tm(&tmesh) { - init(tmesh); + init(tmesh, calculate_epsilon); } -IndexedMesh::IndexedMesh(const TriangleMesh &mesh) +IndexedMesh::IndexedMesh(const TriangleMesh &mesh, bool calculate_epsilon) : m_aabb(new AABBImpl()), m_tm(&mesh.its) { - init(mesh); + init(mesh, calculate_epsilon); } IndexedMesh::~IndexedMesh() {} diff --git a/src/libslic3r/SLA/IndexedMesh.hpp b/src/libslic3r/SLA/IndexedMesh.hpp index 25ab75b83..9348a97c9 100644 --- a/src/libslic3r/SLA/IndexedMesh.hpp +++ b/src/libslic3r/SLA/IndexedMesh.hpp @@ -42,12 +42,14 @@ class IndexedMesh { std::vector m_holes; #endif - template void init(const M &mesh); + template void init(const M &mesh, bool calculate_epsilon); public: - explicit IndexedMesh(const indexed_triangle_set&); - explicit IndexedMesh(const TriangleMesh &mesh); + // calculate_epsilon ... calculate epsilon for triangle-ray intersection from an average triangle edge length. + // If set to false, a default epsilon is used, which works for "reasonable" meshes. + explicit IndexedMesh(const indexed_triangle_set &tmesh, bool calculate_epsilon = false); + explicit IndexedMesh(const TriangleMesh &mesh, bool calculate_epsilon = false); IndexedMesh(const IndexedMesh& other); IndexedMesh& operator=(const IndexedMesh&); diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index d4baabc97..fa8f8bce6 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -1275,6 +1275,21 @@ float its_volume(const indexed_triangle_set &its) return volume; } +float its_average_edge_length(const indexed_triangle_set &its) +{ + if (its.indices.empty()) + return 0.f; + + double edge_length = 0.f; + for (size_t i = 0; i < its.indices.size(); ++ i) { + const its_triangle v = its_triangle_vertices(its, i); + edge_length += (v[1] - v[0]).cast().norm() + + (v[2] - v[0]).cast().norm() + + (v[1] - v[2]).cast().norm(); + } + return float(edge_length / (3 * its.indices.size())); +} + std::vector its_split(const indexed_triangle_set &its) { return its_split<>(its); diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index b7a1bebb1..c463af5a2 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -199,6 +199,7 @@ inline stl_normal its_unnormalized_normal(const indexed_triangle_set &its, } float its_volume(const indexed_triangle_set &its); +float its_average_edge_length(const indexed_triangle_set &its); void its_merge(indexed_triangle_set &A, const indexed_triangle_set &B); void its_merge(indexed_triangle_set &A, const std::vector &triangles); diff --git a/src/slic3r/GUI/MeshUtils.hpp b/src/slic3r/GUI/MeshUtils.hpp index ec6c337c0..65c326116 100644 --- a/src/slic3r/GUI/MeshUtils.hpp +++ b/src/slic3r/GUI/MeshUtils.hpp @@ -112,7 +112,7 @@ public: // The class references extern TriangleMesh, which must stay alive // during MeshRaycaster existence. MeshRaycaster(const TriangleMesh& mesh) - : m_emesh(mesh) + : m_emesh(mesh, true) // calculate epsilon for triangle-ray intersection from an average edge length { m_normals.reserve(mesh.stl.facet_start.size()); for (const stl_facet& facet : mesh.stl.facet_start) From ae3478c6c59ce541f4ee93ebf42c2ba778c98d8e Mon Sep 17 00:00:00 2001 From: David Kocik Date: Sat, 28 Aug 2021 14:35:12 +0200 Subject: [PATCH 30/60] Desktop integration escaping path --- src/slic3r/GUI/DesktopIntegrationDialog.cpp | 98 +++++++++++++++++++-- 1 file changed, 93 insertions(+), 5 deletions(-) diff --git a/src/slic3r/GUI/DesktopIntegrationDialog.cpp b/src/slic3r/GUI/DesktopIntegrationDialog.cpp index fb4a62f91..d34d0730e 100644 --- a/src/slic3r/GUI/DesktopIntegrationDialog.cpp +++ b/src/slic3r/GUI/DesktopIntegrationDialog.cpp @@ -22,6 +22,93 @@ namespace Slic3r { namespace GUI { namespace { + +// escaping of path string according to +// https://cgit.freedesktop.org/xdg/xdg-specs/tree/desktop-entry/desktop-entry-spec.xml +std::string escape_string(const std::string& str) +{ + // The buffer needs to be bigger if escaping <,>,& + std::vector out(str.size() * 2, 0); + char *outptr = out.data(); + for (size_t i = 0; i < str.size(); ++ i) { + char c = str[i]; + // must be escaped + if (c == '\"') { //double quote + (*outptr ++) = '\\'; + (*outptr ++) = '\"'; + } else if (c == '`') { // backtick character + (*outptr ++) = '\\'; + (*outptr ++) = '`'; + } else if (c == '$') { // dollar sign + (*outptr ++) = '\\'; + (*outptr ++) = '$'; + } else if (c == '\\') { // backslash character + (*outptr ++) = '\\'; + (*outptr ++) = '\\'; + // Reserved characters + // At Ubuntu, all these characters must NOT be escaped for desktop integration to work + /* + } else if (c == ' ') { // space + (*outptr ++) = '\\'; + (*outptr ++) = ' '; + } else if (c == '\t') { // tab + (*outptr ++) = '\\'; + (*outptr ++) = '\t'; + } else if (c == '\n') { // newline + (*outptr ++) = '\\'; + (*outptr ++) = '\n'; + } else if (c == '\'') { // single quote + (*outptr ++) = '\\'; + (*outptr ++) = '\''; + } else if (c == '>') { // greater-than sign + (*outptr ++) = '\\'; + (*outptr ++) = '&'; + (*outptr ++) = 'g'; + (*outptr ++) = 't'; + (*outptr ++) = ';'; + } else if (c == '<') { //less-than sign + (*outptr ++) = '\\'; + (*outptr ++) = '&'; + (*outptr ++) = 'l'; + (*outptr ++) = 't'; + (*outptr ++) = ';'; + } else if (c == '~') { // tilde + (*outptr ++) = '\\'; + (*outptr ++) = '~'; + } else if (c == '|') { // vertical bar + (*outptr ++) = '\\'; + (*outptr ++) = '|'; + } else if (c == '&') { // ampersand + (*outptr ++) = '\\'; + (*outptr ++) = '&'; + (*outptr ++) = 'a'; + (*outptr ++) = 'm'; + (*outptr ++) = 'p'; + (*outptr ++) = ';'; + } else if (c == ';') { // semicolon + (*outptr ++) = '\\'; + (*outptr ++) = ';'; + } else if (c == '*') { //asterisk + (*outptr ++) = '\\'; + (*outptr ++) = '*'; + } else if (c == '?') { // question mark + (*outptr ++) = '\\'; + (*outptr ++) = '?'; + } else if (c == '#') { // hash mark + (*outptr ++) = '\\'; + (*outptr ++) = '#'; + } else if (c == '(') { // parenthesis + (*outptr ++) = '\\'; + (*outptr ++) = '('; + } else if (c == ')') { + (*outptr ++) = '\\'; + (*outptr ++) = ')'; + */ + } else + (*outptr ++) = c; + } + return std::string(out.data(), outptr - out.data()); +} // Disects path strings stored in system variable divided by ':' and adds into vector void resolve_path_from_var(const std::string& var, std::vector& paths) { @@ -157,7 +244,8 @@ void DesktopIntegrationDialog::perform_desktop_integration() } // Escape ' characters in appimage, other special symbols will be esacaped in desktop file by 'excutable_path' - boost::replace_all(excutable_path, "'", "'\\''"); + //boost::replace_all(excutable_path, "'", "'\\''"); + excutable_path = escape_string(excutable_path); // Find directories icons and applications // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored. @@ -243,14 +331,14 @@ void DesktopIntegrationDialog::perform_desktop_integration() "Name=PrusaSlicer%1%\n" "GenericName=3D Printing Software\n" "Icon=PrusaSlicer%2%\n" - "Exec=\'%3%\' %%F\n" + "Exec=\"%3%\" %%F\n" "Terminal=false\n" "Type=Application\n" "MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;\n" "Categories=Graphics;3DGraphics;Engineering;\n" "Keywords=3D;Printing;Slicer;slice;3D;printer;convert;gcode;stl;obj;amf;SLA\n" "StartupNotify=false\n" - "StartupWMClass=prusa-slicer", name_suffix, version_suffix, excutable_path); + "StartupWMClass=prusa-slicer\n", name_suffix, version_suffix, excutable_path); std::string path = GUI::format("%1%/applications/PrusaSlicer%2%.desktop", target_dir_desktop, version_suffix); if (create_desktop_file(path, desktop_file)){ @@ -310,13 +398,13 @@ void DesktopIntegrationDialog::perform_desktop_integration() "Name=Prusa Gcode Viewer%1%\n" "GenericName=3D Printing Software\n" "Icon=PrusaSlicer-gcodeviewer%2%\n" - "Exec=\'%3%\' --gcodeviwer %%F\n" + "Exec=\"%3%\" --gcodeviewer %%F\n" "Terminal=false\n" "Type=Application\n" "MimeType=text/x.gcode;\n" "Categories=Graphics;3DGraphics;\n" "Keywords=3D;Printing;Slicer;\n" - "StartupNotify=false", name_suffix, version_suffix, excutable_path); + "StartupNotify=false\n", name_suffix, version_suffix, excutable_path); std::string desktop_path = GUI::format("%1%/applications/PrusaSlicerGcodeViewer%2%.desktop", target_dir_desktop, version_suffix); if (create_desktop_file(desktop_path, desktop_file)) From 14659cf760acf5d2b34b6287c26f601518c202b1 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 30 Aug 2021 08:29:50 +0200 Subject: [PATCH 31/60] Revert of d701dfe436b353f4847b7a78605847f85e50e4eb --- src/slic3r/GUI/GUI_ObjectList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index d4030d41f..b85219c0b 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1049,7 +1049,7 @@ void ObjectList::key_event(wxKeyEvent& event) || event.GetKeyCode() == WXK_BACK #endif //__WXOSX__ ) { - wxGetApp().plater()->remove_selected(); + remove(); } else if (event.GetKeyCode() == WXK_F5) wxGetApp().plater()->reload_all_from_disk(); From 876f9d5a990404b568a67cc088497627072e88ed Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 30 Aug 2021 08:37:41 +0200 Subject: [PATCH 32/60] Cleanup in shader gouraud_light_instanced.vs --- resources/shaders/gouraud_light_instanced.vs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/resources/shaders/gouraud_light_instanced.vs b/resources/shaders/gouraud_light_instanced.vs index 5d6a05a6f..69f58d6e1 100644 --- a/resources/shaders/gouraud_light_instanced.vs +++ b/resources/shaders/gouraud_light_instanced.vs @@ -14,14 +14,12 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); #define INTENSITY_AMBIENT 0.3 -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // vertex attributes in vec3 v_position; in vec3 v_normal; // instance attributes in vec3 i_offset; in vec2 i_scales; -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // x = tainted, y = specular; varying vec2 intensity; @@ -29,29 +27,20 @@ varying vec2 intensity; void main() { // First transform the normal into camera space and normalize the result. -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ vec3 eye_normal = normalize(gl_NormalMatrix * v_normal); -// vec3 eye_normal = normalize(gl_NormalMatrix * gl_Normal); -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0); intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ vec4 world_position = vec4(v_position * vec3(vec2(i_scales.x), i_scales.y) + i_offset, 1.0); vec3 eye_position = (gl_ModelViewMatrix * world_position).xyz; -// vec3 eye_position = (gl_ModelViewMatrix * gl_Vertex).xyz; -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS); // Perform the same lighting calculation for the 2nd light source (no specular applied). NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0); intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ gl_Position = gl_ProjectionMatrix * vec4(eye_position, 1.0); -// gl_Position = ftransform(); -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ } From 6be99f941dcaaf477961ca740ebeae66046d2341 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 30 Aug 2021 10:25:21 +0200 Subject: [PATCH 33/60] Escaping of backslash --- src/slic3r/GUI/DesktopIntegrationDialog.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/DesktopIntegrationDialog.cpp b/src/slic3r/GUI/DesktopIntegrationDialog.cpp index d34d0730e..935121935 100644 --- a/src/slic3r/GUI/DesktopIntegrationDialog.cpp +++ b/src/slic3r/GUI/DesktopIntegrationDialog.cpp @@ -28,7 +28,7 @@ namespace { std::string escape_string(const std::string& str) { // The buffer needs to be bigger if escaping <,>,& - std::vector out(str.size() * 2, 0); + std::vector out(str.size() * 4, 0); char *outptr = out.data(); for (size_t i = 0; i < str.size(); ++ i) { char c = str[i]; @@ -45,6 +45,8 @@ std::string escape_string(const std::string& str) } else if (c == '\\') { // backslash character (*outptr ++) = '\\'; (*outptr ++) = '\\'; + (*outptr ++) = '\\'; + (*outptr ++) = '\\'; // Reserved characters // At Ubuntu, all these characters must NOT be escaped for desktop integration to work /* From 57f7b49223d231d7f160a13c55f6bc8d02c16b13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Mon, 30 Aug 2021 10:41:01 +0200 Subject: [PATCH 34/60] Corrected undo/redo snapshot name when entering or leaving multi-material painting gizmo. --- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp | 3 +++ src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp | 3 +++ src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 10 ++-------- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 3 +++ src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp | 3 +++ 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp index 019ed15f4..f2c19ba5c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.hpp @@ -19,6 +19,9 @@ protected: wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; + std::string get_gizmo_entering_text() const override { return _u8L("Entering Paint-on supports"); } + std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Paint-on supports"); } + private: bool on_init() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index afd5854a0..ab58ba186 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -128,6 +128,9 @@ protected: wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; + std::string get_gizmo_entering_text() const override { return _u8L("Entering Multimaterial painting"); } + std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Multimaterial painting"); } + size_t m_first_selected_extruder_idx = 0; size_t m_second_selected_extruder_idx = 1; std::vector m_original_extruders_names; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index ac9d7adcf..9477b89c7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -47,20 +47,14 @@ void GLGizmoPainterBase::activate_internal_undo_redo_stack(bool activate) plater->undo_redo_topmost_string_getter(plater->can_undo(), last_snapshot_name); if (activate && !m_internal_stack_active) { - std::string str = get_painter_type() == PainterGizmoType::FDM_SUPPORTS - ? _u8L("Entering Paint-on supports") - : _u8L("Entering Seam painting"); - if (last_snapshot_name != str) + if (std::string str = this->get_gizmo_entering_text(); last_snapshot_name != str) Plater::TakeSnapshot(plater, str); plater->enter_gizmos_stack(); m_internal_stack_active = true; } if (!activate && m_internal_stack_active) { plater->leave_gizmos_stack(); - std::string str = get_painter_type() == PainterGizmoType::SEAM - ? _u8L("Leaving Seam painting") - : _u8L("Leaving Paint-on supports"); - if (last_snapshot_name != str) + if (std::string str = this->get_gizmo_leaving_text(); last_snapshot_name != str) Plater::TakeSnapshot(plater, str); m_internal_stack_active = false; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 4db17d597..c20c8140d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -173,6 +173,9 @@ protected: virtual wxString handle_snapshot_action_name(bool shift_down, Button button_down) const = 0; + virtual std::string get_gizmo_entering_text() const = 0; + virtual std::string get_gizmo_leaving_text() const = 0; + friend class ::Slic3r::GUI::GLGizmoMmuSegmentation; }; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp index 196fe5023..7a00a9d8e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.hpp @@ -20,6 +20,9 @@ protected: wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; + std::string get_gizmo_entering_text() const override { return _u8L("Entering Seam painting"); } + std::string get_gizmo_leaving_text() const override { return _u8L("Leaving Seam painting"); } + private: bool on_init() override; From 9c1c72325305455bbf73ad9b76d4b2cc7ed900e9 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 30 Aug 2021 11:46:26 +0200 Subject: [PATCH 35/60] Fixed volume name when loading a 3mf, saved with 3rd part software, as project --- src/libslic3r/Format/3mf.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index e5007a3f4..57b0d8115 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -1837,6 +1837,7 @@ namespace Slic3r { } unsigned int geo_tri_count = (unsigned int)geometry.triangles.size() / 3; + unsigned int renamed_volumes_count = 0; for (const ObjectMetadata::VolumeMetadata& volume_data : volumes) { if (geo_tri_count <= volume_data.first_triangle_id || geo_tri_count <= volume_data.last_triangle_id || volume_data.last_triangle_id < volume_data.first_triangle_id) { @@ -1958,6 +1959,14 @@ namespace Slic3r { else volume->config.set_deserialize(metadata.key, metadata.value, config_substitutions); } + + // this may happen for 3mf saved by 3rd part softwares + if (volume->name.empty()) { + volume->name = object.name; + if (renamed_volumes_count > 0) + volume->name += "_" + std::to_string(renamed_volumes_count + 1); + ++renamed_volumes_count; + } } return true; From c32f2fb7659cc0ac9923e6774bb94382f186ec39 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 30 Aug 2021 12:14:45 +0200 Subject: [PATCH 36/60] New project command enabled when the plater is empty but the project state is marked as dirty --- src/slic3r/GUI/MainFrame.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 329a9a62a..900b9e59f 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -620,7 +620,10 @@ void MainFrame::update_title() wxString dirty_marker = (!m_plater->model().objects.empty() && m_plater->is_project_dirty()) ? "*" : ""; if (!dirty_marker.empty() || !project.empty()) { if (!dirty_marker.empty() && project.empty()) - project = _("Untitled"); +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + project = _L("Untitled"); +// project = _("Untitled"); +//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ title = dirty_marker + project + " - "; } } @@ -819,7 +822,7 @@ bool MainFrame::is_active_and_shown_tab(Tab* tab) bool MainFrame::can_start_new_project() const { - return (m_plater != nullptr) && (!m_plater->get_project_filename(".3mf").IsEmpty() || !m_plater->model().objects.empty()); + return (m_plater != nullptr) && (!m_plater->get_project_filename(".3mf").IsEmpty() || GetTitle().StartsWith('*') || !m_plater->model().objects.empty()); } bool MainFrame::can_save() const From ce3f51379aad8cffb78bac09e235f0cad74de60b Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 30 Aug 2021 14:13:41 +0200 Subject: [PATCH 37/60] ENABLE_SEAMS_USING_MODELS -> Increased size of instances --- src/slic3r/GUI/GCodeViewer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 9ac0536a4..aaea44c7e 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1443,9 +1443,9 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) instances.push_back(curr.position.y()); instances.push_back(curr.position.z()); // append width - instances.push_back(1.2f * curr.width); + instances.push_back(1.5f * curr.width); // append height - instances.push_back(1.2f * curr.height); + instances.push_back(1.5f * curr.height); // append id instances_ids.push_back(move_id); From dcbaf87048543e01289972a9df8b6e4ac669bf34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20Bubn=C3=ADk?= <5830947+bubnikv@users.noreply.github.com> Date: Mon, 30 Aug 2021 14:32:05 +0200 Subject: [PATCH 38/60] Note on desktop integration (PrusaSlicer 2.4) --- doc/How to build - Linux et al.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/How to build - Linux et al.md b/doc/How to build - Linux et al.md index cf47c9392..4a48147dc 100644 --- a/doc/How to build - Linux et al.md +++ b/doc/How to build - Linux et al.md @@ -87,3 +87,13 @@ If you instead want PrusaSlicer installed in a structure according to the File S This will make PrusaSlicer look for a fixed-location `share/slic3r-prusa3d` directory instead (note that the location becomes hardcoded). You can then use the `make install` target to install PrusaSlicer. + +### Desktop Integration (PrusaSlicer 2.4 and newer) + +If PrusaSlicer is to be distributed as an AppImage or a binary blob (.tar.gz and similar), then a desktop integration support is compiled in by default: PrusaSlicer will offer to integrate with desktop by manually copying the desktop file and application icon into user's desktop configuration. The built-in desktop integration is also handy on Crosstini (Linux on Chrome OS). + +If PrusaSlicer is compiled with `SLIC3R_FHS` enabled, then a desktop integration support will not be integrated. One may want to disable desktop integration by running + + cmake .. -DSLIC3R_DESKTOP_INTEGRATION=0 + +when building PrusaSlicer for flatpack or snap, where the desktop integration is performed by the installer. From 87b542597e7a0490bf9ea757865eb2a8afa0cc23 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 30 Aug 2021 14:52:47 +0200 Subject: [PATCH 39/60] Referenced https://github.com/prusa3d/PrusaSlicer/wiki/PrusaSlicer-on-Linux---binary-distributions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b93a47b0..7fdf11bbb 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ # PrusaSlicer You may want to check the [PrusaSlicer project page](https://www.prusa3d.com/prusaslicer/). -Prebuilt Windows, OSX and Linux binaries are available through the [git releases page](https://github.com/prusa3d/PrusaSlicer/releases) or from the [Prusa3D downloads page](https://www.prusa3d.com/drivers/). +Prebuilt Windows, OSX and Linux binaries are available through the [git releases page](https://github.com/prusa3d/PrusaSlicer/releases) or from the [Prusa3D downloads page](https://www.prusa3d.com/drivers/). There are also [3rd party Linux builds available](https://github.com/prusa3d/PrusaSlicer/wiki/PrusaSlicer-on-Linux---binary-distributions). PrusaSlicer takes 3D models (STL, OBJ, AMF) and converts them into G-code instructions for FFF printers or PNG layers for mSLA 3D printers. It's From a571e0f9c46e3b1b59b9a8c32dcc6c26972accec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20Bubn=C3=ADk?= <5830947+bubnikv@users.noreply.github.com> Date: Mon, 30 Aug 2021 15:00:34 +0200 Subject: [PATCH 40/60] Update How to build - Linux et al.md --- doc/How to build - Linux et al.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/How to build - Linux et al.md b/doc/How to build - Linux et al.md index 4a48147dc..299d82381 100644 --- a/doc/How to build - Linux et al.md +++ b/doc/How to build - Linux et al.md @@ -1,6 +1,12 @@ # Building PrusaSlicer on UNIX/Linux +Please understand that PrusaSlicer team cannot support compilation issues on all possible Linux distros. Namely, we cannot help trouble shooting OpenGL driver issues or dependency issues if compiled against distro provided libraries. We can only support PrusaSlicer compiled the same way we do compile PrusaSlicer for our [binary builds](https://github.com/prusa3d/PrusaSlicer/releases), that is linked statically agains the dependencies compiled with the `deps` scripts. + +Instead of compiling PrusaSlicer from source code, you may consider to install PrusaSlicer [pre-compiled by contributors](https://github.com/prusa3d/PrusaSlicer/wiki/PrusaSlicer-on-Linux---binary-distributions). + +### How to build + PrusaSlicer uses the CMake build system and requires several dependencies. The dependencies can be listed in the `deps` directory in individual subdirectories, although they don't necessarily need to be as recent as the versions listed - generally versions available on conservative Linux distros such as Debian stable, Ubuntu LTS releases or Fedora are likely sufficient. From 1e3100d295530bf41d6f1f5b57a70c3904054611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20Bubn=C3=ADk?= <5830947+bubnikv@users.noreply.github.com> Date: Mon, 30 Aug 2021 15:02:30 +0200 Subject: [PATCH 41/60] Update How to build - Linux et al.md --- doc/How to build - Linux et al.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/How to build - Linux et al.md b/doc/How to build - Linux et al.md index 299d82381..c9ad62dc2 100644 --- a/doc/How to build - Linux et al.md +++ b/doc/How to build - Linux et al.md @@ -1,9 +1,9 @@ # Building PrusaSlicer on UNIX/Linux -Please understand that PrusaSlicer team cannot support compilation issues on all possible Linux distros. Namely, we cannot help trouble shooting OpenGL driver issues or dependency issues if compiled against distro provided libraries. We can only support PrusaSlicer compiled the same way we do compile PrusaSlicer for our [binary builds](https://github.com/prusa3d/PrusaSlicer/releases), that is linked statically agains the dependencies compiled with the `deps` scripts. +Please understand that PrusaSlicer team cannot support compilation on all possible Linux distros. Namely, we cannot help trouble shooting OpenGL driver issues or dependency issues if compiled against distro provided libraries. We can only support PrusaSlicer compiled the same way we do compile PrusaSlicer for our [binary builds](https://github.com/prusa3d/PrusaSlicer/releases), that means linked statically agains the dependencies compiled with the `deps` scripts. -Instead of compiling PrusaSlicer from source code, you may consider to install PrusaSlicer [pre-compiled by contributors](https://github.com/prusa3d/PrusaSlicer/wiki/PrusaSlicer-on-Linux---binary-distributions). +Instead of compiling PrusaSlicer from source code, one may consider to install PrusaSlicer [pre-compiled by contributors](https://github.com/prusa3d/PrusaSlicer/wiki/PrusaSlicer-on-Linux---binary-distributions). ### How to build From 9b97414a946401cef4a845345d9683da72b6b582 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Mon, 30 Aug 2021 15:52:24 +0200 Subject: [PATCH 42/60] Mention DEP_DOWNLOAD_DIR in docs Also update dependency report, add CGAL --- doc/Dependencies.md | 3 +++ doc/How to build - Linux et al.md | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/Dependencies.md b/doc/Dependencies.md index 137aaf17b..f37f45466 100644 --- a/doc/Dependencies.md +++ b/doc/Dependencies.md @@ -11,6 +11,9 @@ * openssl * nlopt * openvdb: This library depends on other libs, namely boost, zlib, openexr, blosc (not strictly), etc... +* CGAL: Needs additional dependencies + * MPFR + * GMP ## External libraries in source tree * ad-mesh: Lots of customization, have to be bundled in the source tree. diff --git a/doc/How to build - Linux et al.md b/doc/How to build - Linux et al.md index c9ad62dc2..559536f14 100644 --- a/doc/How to build - Linux et al.md +++ b/doc/How to build - Linux et al.md @@ -38,10 +38,11 @@ Note: We say _mostly independent_ because it's still expected the system will pr To do this, go to the `deps` directory, create a `build` subdirectory (or the like) and use: - cmake .. -DDESTDIR= + cmake .. -DDESTDIR= -DDEP_DOWNLOAD_DIR= where the target destdir is a directory of your choosing where the dependencies will be installed. -You can also omit the `DESTDIR` option to use the default, in that case the `destdir` will be created inside the `build` directory where `cmake` is run. +You can also omit the `DESTDIR` option to use the default, in that case the `destdir` will be created inside the `build` directory where `cmake` is run. The optional `DEP_DOWNLOAD_DIR` argument specifies a directory to cache the downloaded +source packages for each dependent library. Can be useful for repeated builds, to avoid unnecessary network traffic. Once the dependencies have been built, in order to pass the destdir path to the **top-level** PrusaSlicer `CMakeLists.txt` script, use the `CMAKE_PREFIX_PATH` option along with turning on `SLIC3R_STATIC`: From b5742eabe07ffa58e32bed9d8b2c3232b402b602 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 30 Aug 2021 16:38:51 +0200 Subject: [PATCH 43/60] Delayed notifications list Hint notification is delayed until empty notifications --- src/slic3r/GUI/NotificationManager.cpp | 45 +++++++++++++++++++++++++- src/slic3r/GUI/NotificationManager.hpp | 19 +++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 3278a5a6e..9b01cb2fc 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -1369,7 +1369,21 @@ void NotificationManager::push_hint_notification(bool open_next) } NotificationData data{ NotificationType::DidYouKnowHint, NotificationLevel::RegularNotification, 300, "" }; - push_notification_data(std::make_unique(data, m_id_provider, m_evt_handler, open_next), 0); + // from user + if (!open_next) { + push_notification_data(std::make_unique(data, m_id_provider, m_evt_handler, open_next), 0); + // delete from delayed list + for (auto it = m_waiting_notifications.begin(); it != m_waiting_notifications.end();) { + if ((*it).notification->get_type() == NotificationType::DidYouKnowHint) { + it = m_waiting_notifications.erase(it); + } else { + ++it; + } + } + // at startup + } else { + push_delayed_notification(std::make_unique(data, m_id_provider, m_evt_handler, open_next), 500, 30000); + } } bool NotificationManager::is_hint_notification_open() @@ -1425,6 +1439,16 @@ bool NotificationManager::push_notification_data(std::unique_ptr notification, int64_t initial_delay, int64_t delay_interval) +{ + if (initial_delay == 0 && m_pop_notifications.empty()) { + push_notification_data(std::move(notification), 0); + } else { + m_waiting_notifications.emplace_back(std::move(notification), initial_delay, delay_interval); + wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(initial_delay); + } +} + void NotificationManager::render_notifications(GLCanvas3D& canvas, float overlay_width) { sort_notifications(); @@ -1477,6 +1501,25 @@ bool NotificationManager::update_notifications(GLCanvas3D& canvas) ++it; } + // delayed notifications + for (auto it = m_waiting_notifications.begin(); it != m_waiting_notifications.end();) { + // substract time + if ((*it).remaining_time > 0) + (*it).remaining_time -= time_since_render; + if ((*it).remaining_time <= 0) { + if (m_pop_notifications.empty()) { // push notification, erase it from waiting list (frame is scheduled by push) + (*it).notification->reset_timer(); + push_notification_data(std::move((*it).notification), 0); + it = m_waiting_notifications.erase(it); + continue; + } else { // not possible to push, delay for delay_interval + (*it).remaining_time = (*it).delay_interval; + } + } + next_render = std::min(next_render, (*it).remaining_time); + ++it; + } + // request next frame in future if (next_render < max) canvas.schedule_extra_frame(int(next_render)); diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 038290f82..d2a2eb5a7 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -262,6 +262,8 @@ private: EState get_state() const { return m_state; } bool is_hovered() const { return m_state == EState::Hovered; } void set_hovered() { if (m_state != EState::Finished && m_state != EState::ClosePending && m_state != EState::Hidden && m_state != EState::Unknown) m_state = EState::Hovered; } + // set start of notification to now. Used by delayed notifications + void reset_timer() { m_notification_start = GLCanvas3D::timestamp_now(); m_state = EState::Shown; } protected: // Call after every size change virtual void init(); @@ -515,10 +517,25 @@ private: // in HintNotification.hpp class HintNotification; + // Data of waiting notifications + struct DelayedNotification + { + std::unique_ptr notification; + int64_t remaining_time; + int64_t delay_interval; + DelayedNotification(std::unique_ptr n, int64_t r, int64_t d) + : notification(std::move(n)) + , remaining_time(r) + , delay_interval(d) + {} + }; + //pushes notification into the queue of notifications that are rendered //can be used to create custom notification bool push_notification_data(const NotificationData& notification_data, int timestamp); bool push_notification_data(std::unique_ptr notification, int timestamp); + // Delayed notifications goes first to the m_waiting_notifications vector and only after remaining time is <= 0 and m_pop_notifications are empty, notification is regular pushed. Otherwise another delay interval waiting. Timestamp is 0. + void push_delayed_notification(std::unique_ptr notification, int64_t initial_delay, int64_t delay_interval); //finds older notification of same type and moves it to the end of queue. returns true if found bool activate_existing(const NotificationManager::PopNotification* notification); // Put the more important notifications to the bottom of the list. @@ -531,6 +548,8 @@ private: // Cache of IDs to identify and reuse ImGUI windows. NotificationIDProvider m_id_provider; std::deque> m_pop_notifications; + // delayed waiting notifications, first is remaining time + std::deque m_waiting_notifications; //timestamps used for slicing finished - notification could be gone so it needs to be stored here std::unordered_set m_used_timestamps; // True if G-code preview is active. False if the Plater is active. From f92312b597e198ba20fb5b91bb3ceaddee178479 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Mon, 30 Aug 2021 17:56:58 +0200 Subject: [PATCH 44/60] Fixed parsing of Config from AMF / 3MF if it started with an empty line. This bug was introduced with e947a29fc88f098febd2d93a8d9acf8ccedd4229 --- src/libslic3r/Config.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/Config.cpp b/src/libslic3r/Config.cpp index c8a3835dd..ab58a43aa 100644 --- a/src/libslic3r/Config.cpp +++ b/src/libslic3r/Config.cpp @@ -696,10 +696,8 @@ ConfigSubstitutions ConfigBase::load_from_ini_string_commented(std::string &&dat for (size_t i = 0; i < data.size();) if (i == 0 || data[i] == '\n') { // Start of a line. - if (i != 0) { - // Consume LF. - assert(data[i] == '\n'); - // Don't keep empty lines. + if (data[i] == '\n') { + // Consume LF, don't keep empty lines. if (j > 0 && data[j - 1] != '\n') data[j ++] = data[i]; ++ i; From 368e9d7f4e8894284a490f97f9aaa119cad2dec2 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 31 Aug 2021 08:07:38 +0200 Subject: [PATCH 45/60] Do not add an undo/redo snapshot when hitting Del key while nothing is selected --- src/slic3r/GUI/Plater.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index d315e7734..4e9adab62 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5159,8 +5159,11 @@ void Plater::delete_object_from_model(size_t obj_idx) { p->delete_object_from_mo void Plater::remove_selected() { + if (p->get_selection().is_empty()) + return; + Plater::TakeSnapshot snapshot(this, _L("Delete Selected Objects")); - this->p->view3D->delete_selected(); + p->view3D->delete_selected(); } void Plater::increase_instances(size_t num) From 9a5f61c306ce07739579b8ee67a5bfbc8be5f909 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 31 Aug 2021 08:53:40 +0200 Subject: [PATCH 46/60] Added missing vertical alignments of labels in imgui dialogs --- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 1 + src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 9 ++++++++- src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp | 5 ++++- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 3 +-- src/slic3r/GUI/MainFrame.cpp | 3 --- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 4f3e31bea..99c010bf1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -131,6 +131,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l m_imgui->text(""); ImGui::Separator(); + ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc["highlight_by_angle"] + ":"); ImGui::AlignTextToFramePadding(); std::string format_str = std::string("%.f") + I18N::translate_utf8("°", diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 46608b4c7..05e0be141 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -542,6 +542,7 @@ RENDER_AGAIN: m_imgui->disabled_begin(! m_enable_hollowing); float max_tooltip_width = ImGui::GetFontSize() * 20.0f; + ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("offset")); ImGui::SameLine(settings_sliders_left); ImGui::PushItemWidth(window_width - settings_sliders_left); @@ -558,6 +559,7 @@ RENDER_AGAIN: bool slider_released = ImGui::IsItemDeactivatedAfterEdit(); // someone has just released the slider if (current_mode >= quality_mode) { + ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("quality")); ImGui::SameLine(settings_sliders_left); m_imgui->slider_float(" ", &quality, quality_min, quality_max, "%.1f"); @@ -574,6 +576,7 @@ RENDER_AGAIN: } if (current_mode >= closing_d_mode) { + ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("closing_distance")); ImGui::SameLine(settings_sliders_left); m_imgui->slider_float(" ", &closing_d, closing_d_min, closing_d_max, "%.1f mm"); @@ -621,6 +624,7 @@ RENDER_AGAIN: float diameter_upper_cap = 60.; if (m_new_hole_radius * 2.f > diameter_upper_cap) m_new_hole_radius = diameter_upper_cap / 2.f; + ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("hole_diameter")); ImGui::SameLine(diameter_slider_left); ImGui::PushItemWidth(window_width - diameter_slider_left); @@ -636,6 +640,7 @@ RENDER_AGAIN: bool edited = ImGui::IsItemEdited(); bool deactivated = ImGui::IsItemDeactivatedAfterEdit(); + ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc["hole_depth"]); ImGui::SameLine(diameter_slider_left); m_imgui->slider_float(" ", &m_new_hole_height, 0.f, 10.f, "%.1f mm", 1.f, false); @@ -692,8 +697,10 @@ RENDER_AGAIN: // Following is rendered in both editing and non-editing mode: // m_imgui->text(""); ImGui::Separator(); - if (m_c->object_clipper()->get_position() == 0.f) + if (m_c->object_clipper()->get_position() == 0.f) { + ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("clipping_of_view")); + } else { if (m_imgui->button(m_desc.at("reset_direction"))) { wxGetApp().CallAfter([this](){ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index ff9888e19..5b84bbaba 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -138,6 +138,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) const float max_tooltip_width = ImGui::GetFontSize() * 20.0f; + ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("cursor_size")); ImGui::SameLine(cursor_size_slider_left); ImGui::PushItemWidth(window_width - cursor_size_slider_left); @@ -188,8 +189,10 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) ImGui::Separator(); - if (m_c->object_clipper()->get_position() == 0.f) + if (m_c->object_clipper()->get_position() == 0.f) { + ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("clipping_of_view")); + } else { if (m_imgui->button(m_desc.at("reset_direction"))) { wxGetApp().CallAfter([this](){ diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index 40b8d436d..8c90d20d3 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -786,8 +786,7 @@ RENDER_AGAIN: // Following is rendered in both editing and non-editing mode: ImGui::Separator(); - if (m_c->object_clipper()->get_position() == 0.f) - { + if (m_c->object_clipper()->get_position() == 0.f) { ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("clipping_of_view")); } diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 900b9e59f..fa83f4bdf 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -620,10 +620,7 @@ void MainFrame::update_title() wxString dirty_marker = (!m_plater->model().objects.empty() && m_plater->is_project_dirty()) ? "*" : ""; if (!dirty_marker.empty() || !project.empty()) { if (!dirty_marker.empty() && project.empty()) -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ project = _L("Untitled"); -// project = _("Untitled"); -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ title = dirty_marker + project + " - "; } } From 270c076e77663895e69d975e276e3edf6643cc1a Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 30 Aug 2021 17:23:44 +0200 Subject: [PATCH 47/60] Fixed undo/redo issue when clear method of FacetsAnnotation and ModelConfig reset timestamp to 1. This led to a bug where e.g. deleting painted facets through the respective item in object list followed by possible other actions and undo restored the painted facets from the time when the project was loaded. I'm not sure if there was any other situation where this problem manifested. --- src/libslic3r/Model.cpp | 10 +++++----- src/libslic3r/Model.hpp | 5 ++++- src/libslic3r/ObjectID.hpp | 3 --- src/libslic3r/PrintConfig.hpp | 6 ++++-- src/slic3r/GUI/GUI_ObjectList.cpp | 12 ++++++------ src/slic3r/GUI/Plater.cpp | 6 +++--- 6 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 6654d3a13..6f9e4fd4c 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1198,9 +1198,9 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, ModelObjectCutAttr for (ModelVolume *volume : volumes) { const auto volume_matrix = volume->get_matrix(); - volume->supported_facets.clear(); - volume->seam_facets.clear(); - volume->mmu_segmentation_facets.clear(); + volume->supported_facets.reset(); + volume->seam_facets.reset(); + volume->mmu_segmentation_facets.reset(); if (! volume->is_model_part()) { // Modifiers are not cut, but we still need to add the instance transformation @@ -2019,11 +2019,11 @@ bool FacetsAnnotation::set(const TriangleSelector& selector) return false; } -void FacetsAnnotation::clear() +void FacetsAnnotation::reset() { m_data.first.clear(); m_data.second.clear(); - this->reset_timestamp(); + this->touch(); } // Following function takes data from a triangle and encodes it as string diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index b89dd5aa1..ec6fac821 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -541,7 +541,10 @@ public: indexed_triangle_set get_facets_strict(const ModelVolume& mv, EnforcerBlockerType type) const; bool has_facets(const ModelVolume& mv, EnforcerBlockerType type) const; bool empty() const { return m_data.first.empty(); } - void clear(); + + // Following method clears the config and increases its timestamp, so the deleted + // state is considered changed from perspective of the undo/redo stack. + void reset(); // Serialize triangle into string, for serialization into 3MF/AMF. std::string get_triangle_as_string(int i) const; diff --git a/src/libslic3r/ObjectID.hpp b/src/libslic3r/ObjectID.hpp index ea7c748a5..1030171e7 100644 --- a/src/libslic3r/ObjectID.hpp +++ b/src/libslic3r/ObjectID.hpp @@ -105,9 +105,6 @@ protected: // The class tree will have virtual tables and type information. virtual ~ObjectWithTimestamp() = default; - // Resetting timestamp to 1 indicates the object is in its initial (cleared) state. - // To be called by the derived class's clear() method. - void reset_timestamp() { m_timestamp = 1; } // The timestamp uniquely identifies content of the derived class' data, therefore it makes sense to copy the timestamp if the content data was copied. void copy_timestamp(const ObjectWithTimestamp& rhs) { m_timestamp = rhs.m_timestamp; } diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index b15651ba7..64c8445f8 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1064,7 +1064,9 @@ Points get_bed_shape(const SLAPrinterConfig &cfg); class ModelConfig { public: - void clear() { m_data.clear(); m_timestamp = 1; } + // Following method clears the config and increases its timestamp, so the deleted + // state is considered changed from perspective of the undo/redo stack. + void reset() { m_data.clear(); touch(); } void assign_config(const ModelConfig &rhs) { if (m_timestamp != rhs.m_timestamp) { @@ -1076,7 +1078,7 @@ public: if (m_timestamp != rhs.m_timestamp) { m_data = std::move(rhs.m_data); m_timestamp = rhs.m_timestamp; - rhs.clear(); + rhs.reset(); } } diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index b85219c0b..6be9a7acc 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1803,21 +1803,21 @@ void ObjectList::del_info_item(const int obj_idx, InfoItemType type) cnv->get_gizmos_manager().reset_all_states(); Plater::TakeSnapshot(plater, _L("Remove paint-on supports")); for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes) - mv->supported_facets.clear(); + mv->supported_facets.reset(); break; case InfoItemType::CustomSeam: cnv->get_gizmos_manager().reset_all_states(); Plater::TakeSnapshot(plater, _L("Remove paint-on seam")); for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes) - mv->seam_facets.clear(); + mv->seam_facets.reset(); break; case InfoItemType::MmuSegmentation: cnv->get_gizmos_manager().reset_all_states(); Plater::TakeSnapshot(plater, _L("Remove Multi Material painting")); for (ModelVolume* mv : (*m_objects)[obj_idx]->volumes) - mv->mmu_segmentation_facets.clear(); + mv->mmu_segmentation_facets.reset(); break; case InfoItemType::Sinking: @@ -1856,7 +1856,7 @@ void ObjectList::del_settings_from_config(const wxDataViewItem& parent_item) if (is_layer_settings) layer_height = m_config->opt_float("layer_height"); - m_config->clear(); + m_config->reset(); if (extruder >= 0) m_config->set_key_value("extruder", new ConfigOptionInt(extruder)); @@ -1932,7 +1932,7 @@ bool ObjectList::del_subobject_from_object(const int obj_idx, const int idx, con const auto last_volume = object->volumes[0]; if (!last_volume->config.empty()) { object->config.apply(last_volume->config); - last_volume->config.clear(); + last_volume->config.reset(); // update extruder color in ObjectList wxDataViewItem obj_item = m_objects_model->GetItemById(obj_idx); @@ -3769,7 +3769,7 @@ void ObjectList::last_volume_is_deleted(const int obj_idx) auto volume = (*m_objects)[obj_idx]->volumes.front(); // clear volume's config values - volume->config.clear(); + volume->config.reset(); // set a default extruder value, since user can't add it manually volume->config.set_key_value("extruder", new ConfigOptionInt(0)); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 4e9adab62..e8ce90516 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6217,9 +6217,9 @@ void Plater::clear_before_change_mesh(int obj_idx) bool paint_removed = false; for (ModelVolume* mv : mo->volumes) { paint_removed |= ! mv->supported_facets.empty() || ! mv->seam_facets.empty() || ! mv->mmu_segmentation_facets.empty(); - mv->supported_facets.clear(); - mv->seam_facets.clear(); - mv->mmu_segmentation_facets.clear(); + mv->supported_facets.reset(); + mv->seam_facets.reset(); + mv->mmu_segmentation_facets.reset(); } if (paint_removed) { // snapshot_time is captured by copy so the lambda knows where to undo/redo to. From 86ddac7b1ec4e9a1ff33b11363e55607b2a09f55 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 31 Aug 2021 09:17:52 +0200 Subject: [PATCH 48/60] Fixed warning --- src/slic3r/GUI/GCodeViewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index aaea44c7e..732403b03 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -2665,7 +2665,7 @@ void GCodeViewer::render_toolpaths() }; #if ENABLE_SEAMS_USING_MODELS - auto render_as_instanced_model = [this] + auto render_as_instanced_model = [] (TBuffer& buffer, GLShaderProgram & shader) { for (auto& range : buffer.model.instances.render_ranges.ranges) { if (range.vbo == 0 && range.count > 0) { From 04778e0fa55dee620637f2e7a5615711655cc182 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Tue, 31 Aug 2021 10:34:39 +0200 Subject: [PATCH 49/60] delayed notifications: custom condition function for showing and refactoring --- src/slic3r/GUI/NotificationManager.cpp | 65 +++++++++++++++++--------- src/slic3r/GUI/NotificationManager.hpp | 17 +++++-- 2 files changed, 56 insertions(+), 26 deletions(-) diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 9b01cb2fc..219faf42e 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -1369,20 +1369,17 @@ void NotificationManager::push_hint_notification(bool open_next) } NotificationData data{ NotificationType::DidYouKnowHint, NotificationLevel::RegularNotification, 300, "" }; - // from user + // from user - open now if (!open_next) { push_notification_data(std::make_unique(data, m_id_provider, m_evt_handler, open_next), 0); - // delete from delayed list - for (auto it = m_waiting_notifications.begin(); it != m_waiting_notifications.end();) { - if ((*it).notification->get_type() == NotificationType::DidYouKnowHint) { - it = m_waiting_notifications.erase(it); - } else { - ++it; - } - } - // at startup + stop_delayed_notifications_of_type(NotificationType::DidYouKnowHint); + // at startup - delay for half a second to let other notification pop up, than try every 30 seconds + // show only if no notifications are shown } else { - push_delayed_notification(std::make_unique(data, m_id_provider, m_evt_handler, open_next), 500, 30000); + auto condition = [this]() { + return this->get_notification_count() == 0; + }; + push_delayed_notification(std::make_unique(data, m_id_provider, m_evt_handler, open_next), condition, 500, 30000); } } @@ -1439,13 +1436,25 @@ bool NotificationManager::push_notification_data(std::unique_ptr notification, int64_t initial_delay, int64_t delay_interval) +void NotificationManager::push_delayed_notification(std::unique_ptr notification, std::function condition_callback, int64_t initial_delay, int64_t delay_interval) { - if (initial_delay == 0 && m_pop_notifications.empty()) { - push_notification_data(std::move(notification), 0); - } else { - m_waiting_notifications.emplace_back(std::move(notification), initial_delay, delay_interval); - wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(initial_delay); + if (initial_delay == 0 && condition_callback()) { + if( push_notification_data(std::move(notification), 0)) + return; + } + m_waiting_notifications.emplace_back(std::move(notification), condition_callback, initial_delay == 0 ? delay_interval : initial_delay, delay_interval); + wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(initial_delay == 0 ? delay_interval : initial_delay); +} + +void NotificationManager::stop_delayed_notifications_of_type(const NotificationType type) +{ + for (auto it = m_waiting_notifications.begin(); it != m_waiting_notifications.end();) { + if ((*it).notification->get_type() == type) { + it = m_waiting_notifications.erase(it); + } + else { + ++it; + } } } @@ -1507,14 +1516,15 @@ bool NotificationManager::update_notifications(GLCanvas3D& canvas) if ((*it).remaining_time > 0) (*it).remaining_time -= time_since_render; if ((*it).remaining_time <= 0) { - if (m_pop_notifications.empty()) { // push notification, erase it from waiting list (frame is scheduled by push) + if ((*it).condition_callback()) { // push notification, erase it from waiting list (frame is scheduled by push) (*it).notification->reset_timer(); - push_notification_data(std::move((*it).notification), 0); - it = m_waiting_notifications.erase(it); - continue; - } else { // not possible to push, delay for delay_interval - (*it).remaining_time = (*it).delay_interval; + if (push_notification_data(std::move((*it).notification), 0)) { + it = m_waiting_notifications.erase(it); + continue; + } } + // not possible to push, delay for delay_interval + (*it).remaining_time = (*it).delay_interval; } next_render = std::min(next_render, (*it).remaining_time); ++it; @@ -1612,6 +1622,15 @@ void NotificationManager::device_ejected() notification->close(); } } +size_t NotificationManager::get_notification_count() const +{ + size_t ret = 0; + for (const std::unique_ptr& notification : m_pop_notifications) { + if (notification->get_state() != PopNotification::EState::Hidden) + ret++; + } + return ret; +} }//namespace GUI }//namespace Slic3r diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index d2a2eb5a7..4aba35f4c 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -190,6 +190,8 @@ public: void set_move_from_overlay(bool move) { m_move_from_overlay = move; } // perform update_state on each notification and ask for more frames if needed, return true for render needed bool update_notifications(GLCanvas3D& canvas); + // returns number of all notifications shown + size_t get_notification_count() const; private: // duration 0 means not disapearing struct NotificationData { @@ -521,10 +523,13 @@ private: struct DelayedNotification { std::unique_ptr notification; + std::function condition_callback; int64_t remaining_time; int64_t delay_interval; - DelayedNotification(std::unique_ptr n, int64_t r, int64_t d) + + DelayedNotification(std::unique_ptr n, std::function cb, int64_t r, int64_t d) : notification(std::move(n)) + , condition_callback(cb) , remaining_time(r) , delay_interval(d) {} @@ -534,8 +539,14 @@ private: //can be used to create custom notification bool push_notification_data(const NotificationData& notification_data, int timestamp); bool push_notification_data(std::unique_ptr notification, int timestamp); - // Delayed notifications goes first to the m_waiting_notifications vector and only after remaining time is <= 0 and m_pop_notifications are empty, notification is regular pushed. Otherwise another delay interval waiting. Timestamp is 0. - void push_delayed_notification(std::unique_ptr notification, int64_t initial_delay, int64_t delay_interval); + // Delayed notifications goes first to the m_waiting_notifications vector and only after remaining time is <= 0 + // and condition callback is success, notification is regular pushed from update function. + // Otherwise another delay interval waiting. Timestamp is 0. + // Note that notification object is constructed when being added to the waiting list, but there are no updates called on it and its timer is reset at regular push. + // Also note that no control of same notification is done during push_delayed_notification but if waiting notif fails to push, it continues waiting. + void push_delayed_notification(std::unique_ptr notification, std::function condition_callback, int64_t initial_delay, int64_t delay_interval); + // Removes all notifications of type from m_waiting_notifications + void stop_delayed_notifications_of_type(const NotificationType type); //finds older notification of same type and moves it to the end of queue. returns true if found bool activate_existing(const NotificationManager::PopNotification* notification); // Put the more important notifications to the bottom of the list. From 788d114a2fe727015b6622d4699d04a1ce2221c7 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Tue, 31 Aug 2021 11:26:00 +0200 Subject: [PATCH 50/60] Passing call_selection_changed to update_info_items. Helps to decide correctly if object was added or only undo / redo operation. --- src/slic3r/GUI/GUI_ObjectList.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 6be9a7acc..82f03f51a 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2637,7 +2637,7 @@ void ObjectList::add_object_to_list(size_t obj_idx, bool call_selection_changed) model_object->config.has("extruder") ? model_object->config.extruder() : 0, get_mesh_errors_count(obj_idx) > 0); - update_info_items(obj_idx, nullptr, true); + update_info_items(obj_idx, nullptr, call_selection_changed); // add volumes to the object if (model_object->volumes.size() > 1) { From 4cc729b312533e8b2001b93b51f0f15c69229a78 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 31 Aug 2021 12:05:06 +0200 Subject: [PATCH 51/60] Fixed encoding of undo/redo snapshot names created through TakeSnapshot class (implicit std::string/wxString conversion) --- src/slic3r/GUI/Plater.cpp | 5 +++++ src/slic3r/GUI/Plater.hpp | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e8ce90516..14350bddf 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6581,6 +6581,11 @@ bool Plater::is_render_statistic_dialog_visible() const return p->show_render_statistic_dialog; } + +Plater::TakeSnapshot::TakeSnapshot(Plater *plater, const std::string &snapshot_name) +: TakeSnapshot(plater, from_u8(snapshot_name)) {} + + // Wrapper around wxWindow::PopupMenu to suppress error messages popping out while tracking the popup menu. bool Plater::PopupMenu(wxMenu *menu, const wxPoint& pos) { diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 3556756e2..99f7e3cda 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -383,10 +383,11 @@ public: Plater *m_plater; }; - // ROII wrapper for taking an Undo / Redo snapshot while disabling the snapshot taking by the methods called from inside this snapshot. + // RAII wrapper for taking an Undo / Redo snapshot while disabling the snapshot taking by the methods called from inside this snapshot. class TakeSnapshot { public: + TakeSnapshot(Plater *plater, const std::string &snapshot_name); TakeSnapshot(Plater *plater, const wxString &snapshot_name) : m_plater(plater) { m_plater->take_snapshot(snapshot_name); From 5f26bfd3974c006f3aa0e419c2f7f866225d50de Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 31 Aug 2021 12:22:38 +0200 Subject: [PATCH 52/60] Brim separation from object, follow up to 82373334bcdaaaf10ed860fd2887b635f815d81f 1) Changed the name of the variable "brim_offset" to "brim_separation" for clarity. 2) Added legacy conversion after loading an old 3MF that does not define then new "brim_separation" variable: The "brim_separation" is being filled in with the "elefant_foot_compensation" value to produce equal brim separation to the old PrusaSlicer that saved that 3MF file. --- resources/profiles/PrusaResearch.idx | 2 +- resources/profiles/PrusaResearch.ini | 2 +- src/libslic3r/Brim.cpp | 26 +++++++++++++------------- src/libslic3r/Format/3mf.cpp | 15 +++++++++++++++ src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 6 +++--- src/libslic3r/PrintConfig.hpp | 2 +- src/libslic3r/PrintObject.cpp | 2 +- src/libslic3r/SupportMaterial.cpp | 14 +++++++------- src/slic3r/GUI/ConfigManipulation.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 2 +- 12 files changed, 46 insertions(+), 31 deletions(-) diff --git a/resources/profiles/PrusaResearch.idx b/resources/profiles/PrusaResearch.idx index 37d144ff0..8a34a9a11 100644 --- a/resources/profiles/PrusaResearch.idx +++ b/resources/profiles/PrusaResearch.idx @@ -1,5 +1,5 @@ min_slic3r_version = 2.4.0-alpha0 -1.4.0-alpha7 Updated brim_offset value. Updated Prusa MINI end g-code. Added Filamentworld filament profiles. +1.4.0-alpha7 Updated brim_separation value. Updated Prusa MINI end g-code. Added Filamentworld filament profiles. 1.4.0-alpha6 Added nozzle priming after M600. Added nozzle diameter checks for 0.8 nozzle printer profiles. Updated FW version. Increased number of top solid infill layers (0.2 layer height). 1.4.0-alpha5 Added multiple add:north and Extrudr filament profiles. Updated support head settings (SL1S). 1.4.0-alpha4 Decreased Area Fill (SL1S). diff --git a/resources/profiles/PrusaResearch.ini b/resources/profiles/PrusaResearch.ini index 0ed5b59a6..835e552a1 100644 --- a/resources/profiles/PrusaResearch.ini +++ b/resources/profiles/PrusaResearch.ini @@ -144,7 +144,7 @@ bridge_angle = 0 bridge_flow_ratio = 1 bridge_speed = 25 brim_width = 0 -brim_offset = 0.1 +brim_separation = 0.1 clip_multipart_objects = 1 compatible_printers = complete_objects = 0 diff --git a/src/libslic3r/Brim.cpp b/src/libslic3r/Brim.cpp index f4455fdd5..f20404bc9 100644 --- a/src/libslic3r/Brim.cpp +++ b/src/libslic3r/Brim.cpp @@ -134,10 +134,10 @@ static Polygons top_level_outer_brim_islands(const ConstPrintObjectPtrs &top_lev Polygons islands; for (const PrintObject *object : top_level_objects_with_brim) { //FIXME how about the brim type? - auto brim_offset = float(scale_(object->config().brim_offset.value)); + auto brim_separation = float(scale_(object->config().brim_separation.value)); Polygons islands_object; for (const ExPolygon &ex_poly : get_print_object_bottom_layer_expolygons(*object)) { - Polygons contour_offset = offset(ex_poly.contour, brim_offset); + Polygons contour_offset = offset(ex_poly.contour, brim_separation); for (Polygon &poly : contour_offset) poly.douglas_peucker(SCALED_RESOLUTION); @@ -166,7 +166,7 @@ static ExPolygons top_level_outer_brim_area(const Print &print for(size_t print_object_idx = 0; print_object_idx < print.objects().size(); ++print_object_idx) { const PrintObject *object = print.objects()[print_object_idx]; const BrimType brim_type = object->config().brim_type.value; - const float brim_offset = scale_(object->config().brim_offset.value); + const float brim_separation = scale_(object->config().brim_separation.value); const float brim_width = scale_(object->config().brim_width.value); const bool is_top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end(); @@ -174,7 +174,7 @@ static ExPolygons top_level_outer_brim_area(const Print &print ExPolygons no_brim_area_object; for (const ExPolygon &ex_poly : bottom_layers_expolygons[print_object_idx]) { if ((brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner) && is_top_outer_brim) - append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_offset), offset(ex_poly.contour, brim_offset))); + append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_separation), offset(ex_poly.contour, brim_separation))); if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim) append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset)); @@ -183,7 +183,7 @@ static ExPolygons top_level_outer_brim_area(const Print &print append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset), ex_poly.holes)); if (brim_type != BrimType::btNoBrim) - append(no_brim_area_object, offset_ex(ExPolygon(ex_poly.contour), brim_offset)); + append(no_brim_area_object, offset_ex(ExPolygon(ex_poly.contour), brim_separation)); no_brim_area_object.emplace_back(ex_poly.contour); } @@ -212,11 +212,11 @@ static ExPolygons inner_brim_area(const Print &print, ExPolygons no_brim_area; Polygons holes; for(size_t print_object_idx = 0; print_object_idx < print.objects().size(); ++print_object_idx) { - const PrintObject *object = print.objects()[print_object_idx]; - const BrimType brim_type = object->config().brim_type.value; - const float brim_offset = scale_(object->config().brim_offset.value); - const float brim_width = scale_(object->config().brim_width.value); - const bool top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end(); + const PrintObject *object = print.objects()[print_object_idx]; + const BrimType brim_type = object->config().brim_type.value; + const float brim_separation = scale_(object->config().brim_separation.value); + const float brim_width = scale_(object->config().brim_width.value); + const bool top_outer_brim = top_level_objects_idx.find(object->id().id) != top_level_objects_idx.end(); ExPolygons brim_area_object; ExPolygons no_brim_area_object; @@ -226,11 +226,11 @@ static ExPolygons inner_brim_area(const Print &print, if (top_outer_brim) no_brim_area_object.emplace_back(ex_poly); else - append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_offset), offset(ex_poly.contour, brim_offset))); + append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_separation), offset(ex_poly.contour, brim_separation))); } if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btOuterAndInner) - append(brim_area_object, diff_ex(offset_ex(ex_poly.holes, -brim_offset), offset_ex(ex_poly.holes, -brim_width - brim_offset))); + append(brim_area_object, diff_ex(offset_ex(ex_poly.holes, -brim_separation), offset_ex(ex_poly.holes, -brim_width - brim_separation))); if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim) append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset), ex_poly.holes)); @@ -240,7 +240,7 @@ static ExPolygons inner_brim_area(const Print &print, append(holes_object, ex_poly.holes); } - append(no_brim_area_object, offset_ex(bottom_layers_expolygons[print_object_idx], brim_offset)); + append(no_brim_area_object, offset_ex(bottom_layers_expolygons[print_object_idx], brim_separation)); for (const PrintInstance &instance : object->instances()) { append_and_translate(brim_area, brim_area_object, instance); diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 57b0d8115..74969b523 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -420,6 +420,7 @@ namespace Slic3r { ~_3MF_Importer(); bool load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config, ConfigSubstitutionContext& config_substitutions, bool check_version); + unsigned int version() const { return m_version; } private: void _destroy_xml_parser(); @@ -2990,6 +2991,19 @@ bool _3MF_Exporter::_add_custom_gcode_per_print_z_file_to_archive( mz_zip_archiv return true; } +// Perform conversions based on the config values available. +//FIXME provide a version of PrusaSlicer that stored the project file (3MF). +static void handle_legacy_project_loaded(unsigned int version_project_file, DynamicPrintConfig& config) +{ + if (! config.has("brim_separation")) { + if (auto *opt_elephant_foot = config.option("elefant_foot_compensation", false); opt_elephant_foot) { + // Conversion from older PrusaSlicer which applied brim separation equal to elephant foot compensation. + auto *opt_brim_separation = config.option("brim_separation", true); + opt_brim_separation->value = opt_elephant_foot->value; + } + } +} + bool load_3mf(const char* path, DynamicPrintConfig& config, ConfigSubstitutionContext& config_substitutions, Model* model, bool check_version) { if (path == nullptr || model == nullptr) @@ -3000,6 +3014,7 @@ bool load_3mf(const char* path, DynamicPrintConfig& config, ConfigSubstitutionCo _3MF_Importer importer; bool res = importer.load_model_from_file(path, *model, config, config_substitutions, check_version); importer.log_errors(); + handle_legacy_project_loaded(importer.version(), config); return res; } diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 3883c4980..564300baf 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -430,7 +430,7 @@ static std::vector s_Preset_print_options { "top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed", "bridge_speed", "gap_fill_speed", "gap_fill_enabled", "travel_speed", "travel_speed_z", "first_layer_speed", "perimeter_acceleration", "infill_acceleration", "bridge_acceleration", "first_layer_acceleration", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield", - "min_skirt_length", "brim_width", "brim_offset", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", + "min_skirt_length", "brim_width", "brim_separation", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", "raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion", "support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_closing_radius", "support_material_style", "support_material_synchronize_layers", "support_material_angle", "support_material_interface_layers", "support_material_bottom_interface_layers", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index f010bad39..b5c1cbeb3 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -505,10 +505,10 @@ void PrintConfigDef::init_fff_params() def->mode = comSimple; def->set_default_value(new ConfigOptionEnum(btOuterOnly)); - def = this->add("brim_offset", coFloat); - def->label = L("Brim offset"); + def = this->add("brim_separation", coFloat); + def->label = L("Brim separation gap"); def->category = L("Skirt and brim"); - def->tooltip = L("The offset of the brim from the printed object. The offset is applied after the elephant foot compensation."); + def->tooltip = L("Offset of brim from the printed object. The offset is applied after the elephant foot compensation."); def->sidetext = L("mm"); def->min = 0; def->mode = comAdvanced; diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 64c8445f8..f5070c54d 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -449,7 +449,7 @@ protected: \ PRINT_CONFIG_CLASS_DEFINE( PrintObjectConfig, - ((ConfigOptionFloat, brim_offset)) + ((ConfigOptionFloat, brim_separation)) ((ConfigOptionEnum, brim_type)) ((ConfigOptionFloat, brim_width)) ((ConfigOptionBool, clip_multipart_objects)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index d8d26baa6..f0eaa982a 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -500,7 +500,7 @@ bool PrintObject::invalidate_state_by_config_options( bool invalidated = false; for (const t_config_option_key &opt_key : opt_keys) { if ( opt_key == "brim_width" - || opt_key == "brim_offset" + || opt_key == "brim_separation" || opt_key == "brim_type") { // Brim is printed below supports, support invalidates brim and skirt. steps.emplace_back(posSupportMaterial); diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index 2e4a47954..1b66bcc53 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -2810,22 +2810,22 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf Polygons brim; if (object.has_brim()) { // Calculate the area covered by the brim. - const BrimType brim_type = object.config().brim_type; - const bool brim_outer = brim_type == btOuterOnly || brim_type == btOuterAndInner; - const bool brim_inner = brim_type == btInnerOnly || brim_type == btOuterAndInner; - const auto brim_offset = scaled(object.config().brim_offset.value + object.config().brim_width.value); + const BrimType brim_type = object.config().brim_type; + const bool brim_outer = brim_type == btOuterOnly || brim_type == btOuterAndInner; + const bool brim_inner = brim_type == btInnerOnly || brim_type == btOuterAndInner; + const auto brim_separation = scaled(object.config().brim_separation.value + object.config().brim_width.value); for (const ExPolygon &ex : object.layers().front()->lslices) { if (brim_outer && brim_inner) - polygons_append(brim, offset(ex, brim_offset)); + polygons_append(brim, offset(ex, brim_separation)); else { if (brim_outer) - polygons_append(brim, offset(ex.contour, brim_offset, ClipperLib::jtRound, float(scale_(0.1)))); + polygons_append(brim, offset(ex.contour, brim_separation, ClipperLib::jtRound, float(scale_(0.1)))); else brim.emplace_back(ex.contour); if (brim_inner) { Polygons holes = ex.holes; polygons_reverse(holes); - holes = offset(holes, - brim_offset, ClipperLib::jtRound, float(scale_(0.1))); + holes = offset(holes, - brim_separation, ClipperLib::jtRound, float(scale_(0.1))); polygons_reverse(holes); polygons_append(brim, std::move(holes)); } else diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 54b87786a..72584e938 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -281,7 +281,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) toggle_field(el, have_skirt); bool have_brim = config->opt_enum("brim_type") != btNoBrim; - for (auto el : { "brim_width", "brim_offset" }) + for (auto el : { "brim_width", "brim_separation" }) toggle_field(el, have_brim); // perimeter_extruder uses the same logic as in Print::extruders() toggle_field("perimeter_extruder", have_perimeters || have_brim); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 14350bddf..743f27578 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1834,7 +1834,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) , main_frame(main_frame) , config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({ "bed_shape", "bed_custom_texture", "bed_custom_model", "complete_objects", "duplicate_distance", "extruder_clearance_radius", "skirts", "skirt_distance", - "brim_width", "brim_offset", "brim_type", "variable_layer_height", "nozzle_diameter", "single_extruder_multi_material", + "brim_width", "brim_separation", "brim_type", "variable_layer_height", "nozzle_diameter", "single_extruder_multi_material", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "extruder_colour", "filament_colour", "max_print_height", "printer_model", "printer_technology", // These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor. diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index bc4c6b728..6bd295fdc 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1509,7 +1509,7 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Brim")); optgroup->append_single_option_line("brim_type", category_path + "brim"); optgroup->append_single_option_line("brim_width", category_path + "brim"); - optgroup->append_single_option_line("brim_offset", category_path + "brim"); + optgroup->append_single_option_line("brim_separation", category_path + "brim"); page = add_options_page(L("Support material"), "support"); category_path = "support-material_1698#"; From c797bed67d0db1281fb0820238aa811a4b66fcdf Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 31 Aug 2021 14:35:32 +0200 Subject: [PATCH 53/60] Changed vertex attributes syntax in gouraud_light_instanced.vs --- resources/shaders/gouraud_light_instanced.vs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/shaders/gouraud_light_instanced.vs b/resources/shaders/gouraud_light_instanced.vs index 69f58d6e1..a8931361d 100644 --- a/resources/shaders/gouraud_light_instanced.vs +++ b/resources/shaders/gouraud_light_instanced.vs @@ -15,11 +15,11 @@ const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074); #define INTENSITY_AMBIENT 0.3 // vertex attributes -in vec3 v_position; -in vec3 v_normal; +attribute vec3 v_position; +attribute vec3 v_normal; // instance attributes -in vec3 i_offset; -in vec2 i_scales; +attribute vec3 i_offset; +attribute vec2 i_scales; // x = tainted, y = specular; varying vec2 intensity; From 1835dae296f52f6704fbaee25f504d18dae589dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Mon, 30 Aug 2021 15:51:16 +0200 Subject: [PATCH 54/60] Fixed a bug that the skirt was generated too far from the brim for some objects. --- src/libslic3r/Brim.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/Brim.cpp b/src/libslic3r/Brim.cpp index f20404bc9..db31975e3 100644 --- a/src/libslic3r/Brim.cpp +++ b/src/libslic3r/Brim.cpp @@ -137,7 +137,7 @@ static Polygons top_level_outer_brim_islands(const ConstPrintObjectPtrs &top_lev auto brim_separation = float(scale_(object->config().brim_separation.value)); Polygons islands_object; for (const ExPolygon &ex_poly : get_print_object_bottom_layer_expolygons(*object)) { - Polygons contour_offset = offset(ex_poly.contour, brim_separation); + Polygons contour_offset = offset(ex_poly.contour, brim_separation, ClipperLib::jtSquare); for (Polygon &poly : contour_offset) poly.douglas_peucker(SCALED_RESOLUTION); @@ -174,16 +174,16 @@ static ExPolygons top_level_outer_brim_area(const Print &print ExPolygons no_brim_area_object; for (const ExPolygon &ex_poly : bottom_layers_expolygons[print_object_idx]) { if ((brim_type == BrimType::btOuterOnly || brim_type == BrimType::btOuterAndInner) && is_top_outer_brim) - append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_separation), offset(ex_poly.contour, brim_separation))); + append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_separation, ClipperLib::jtSquare), offset(ex_poly.contour, brim_separation, ClipperLib::jtSquare))); if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset)); + append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset, ClipperLib::jtSquare)); if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset), ex_poly.holes)); + append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset, ClipperLib::jtSquare), ex_poly.holes)); if (brim_type != BrimType::btNoBrim) - append(no_brim_area_object, offset_ex(ExPolygon(ex_poly.contour), brim_separation)); + append(no_brim_area_object, offset_ex(ExPolygon(ex_poly.contour), brim_separation, ClipperLib::jtSquare)); no_brim_area_object.emplace_back(ex_poly.contour); } @@ -226,21 +226,21 @@ static ExPolygons inner_brim_area(const Print &print, if (top_outer_brim) no_brim_area_object.emplace_back(ex_poly); else - append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_separation), offset(ex_poly.contour, brim_separation))); + append(brim_area_object, diff_ex(offset(ex_poly.contour, brim_width + brim_separation, ClipperLib::jtSquare), offset(ex_poly.contour, brim_separation, ClipperLib::jtSquare))); } if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btOuterAndInner) - append(brim_area_object, diff_ex(offset_ex(ex_poly.holes, -brim_separation), offset_ex(ex_poly.holes, -brim_width - brim_separation))); + append(brim_area_object, diff_ex(offset_ex(ex_poly.holes, -brim_separation, ClipperLib::jtSquare), offset_ex(ex_poly.holes, -brim_width - brim_separation, ClipperLib::jtSquare))); if (brim_type == BrimType::btInnerOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset), ex_poly.holes)); + append(no_brim_area_object, diff_ex(offset(ex_poly.contour, no_brim_offset, ClipperLib::jtSquare), ex_poly.holes)); if (brim_type == BrimType::btOuterOnly || brim_type == BrimType::btNoBrim) - append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset)); + append(no_brim_area_object, offset_ex(ex_poly.holes, -no_brim_offset, ClipperLib::jtSquare)); append(holes_object, ex_poly.holes); } - append(no_brim_area_object, offset_ex(bottom_layers_expolygons[print_object_idx], brim_separation)); + append(no_brim_area_object, offset_ex(bottom_layers_expolygons[print_object_idx], brim_separation, ClipperLib::jtSquare)); for (const PrintInstance &instance : object->instances()) { append_and_translate(brim_area, brim_area_object, instance); @@ -356,12 +356,12 @@ static void make_inner_brim(const Print &print, Flow flow = print.brim_flow(); ExPolygons islands_ex = inner_brim_area(print, top_level_objects_with_brim, bottom_layers_expolygons, float(flow.scaled_spacing())); Polygons loops; - islands_ex = offset_ex(islands_ex, -0.5f * float(flow.scaled_spacing()), jtSquare); + islands_ex = offset_ex(islands_ex, -0.5f * float(flow.scaled_spacing()), ClipperLib::jtSquare); for (size_t i = 0; !islands_ex.empty(); ++i) { for (ExPolygon &poly_ex : islands_ex) poly_ex.douglas_peucker(SCALED_RESOLUTION); polygons_append(loops, to_polygons(islands_ex)); - islands_ex = offset_ex(islands_ex, -float(flow.scaled_spacing()), jtSquare); + islands_ex = offset_ex(islands_ex, -float(flow.scaled_spacing()), ClipperLib::jtSquare); } loops = union_pt_chained_outside_in(loops); @@ -385,7 +385,7 @@ ExtrusionEntityCollection make_brim(const Print &print, PrintTryCancel try_cance size_t num_loops = size_t(floor(max_brim_width(print.objects()) / flow.spacing())); for (size_t i = 0; i < num_loops; ++i) { try_cancel(); - islands = offset(islands, float(flow.scaled_spacing()), jtSquare); + islands = offset(islands, float(flow.scaled_spacing()), ClipperLib::jtSquare); for (Polygon &poly : islands) poly.douglas_peucker(SCALED_RESOLUTION); polygons_append(loops, offset(islands, -0.5f * float(flow.scaled_spacing()))); From ccf671dcc983b63627fa61f3db6f594e0cb772ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Tue, 31 Aug 2021 08:03:09 +0200 Subject: [PATCH 55/60] Added versioning of the structure of stored data for all three painting gizmos (fdm supports, seam and multi-material). --- src/libslic3r/Format/3mf.cpp | 52 ++++++++++++++++++++++++++++++++++++ src/libslic3r/Model.cpp | 25 +++++++++++++++++ src/libslic3r/Model.hpp | 13 +++++++++ 3 files changed, 90 insertions(+) diff --git a/src/libslic3r/Format/3mf.cpp b/src/libslic3r/Format/3mf.cpp index 74969b523..cde7d0a43 100644 --- a/src/libslic3r/Format/3mf.cpp +++ b/src/libslic3r/Format/3mf.cpp @@ -49,6 +49,17 @@ const unsigned int VERSION_3MF = 1; const unsigned int VERSION_3MF_COMPATIBLE = 2; const char* SLIC3RPE_3MF_VERSION = "slic3rpe:Version3mf"; // definition of the metadata name saved into .model file +// Painting gizmos data version numbers +// 0 : 3MF files saved by older PrusaSlicer or the painting gizmo wasn't used. No version definition in them. +// 1 : Introduction of painting gizmos data versioning. No other changes in painting gizmos data. +const unsigned int FDM_SUPPORTS_PAINTING_VERSION = 1; +const unsigned int SEAM_PAINTING_VERSION = 1; +const unsigned int MM_PAINTING_VERSION = 1; + +const std::string SLIC3RPE_FDM_SUPPORTS_PAINTING_VERSION = "slic3rpe:FdmSupportsPaintingVersion"; +const std::string SLIC3RPE_SEAM_PAINTING_VERSION = "slic3rpe:SeamPaintingVersion"; +const std::string SLIC3RPE_MM_PAINTING_VERSION = "slic3rpe:MmPaintingVersion"; + const std::string MODEL_FOLDER = "3D/"; const std::string MODEL_EXTENSION = ".model"; const std::string MODEL_FILE = "3D/3dmodel.model"; // << this is the only format of the string which works with CURA @@ -393,6 +404,10 @@ namespace Slic3r { unsigned int m_version; bool m_check_version; + unsigned int m_fdm_supports_painting_version = 0; + unsigned int m_seam_painting_version = 0; + unsigned int m_mm_painting_version = 0; + XML_Parser m_xml_parser; // Error code returned by the application side of the parser. In that case the expat may not reliably deliver the error state // after returning from XML_Parse() function, thus we keep the error state here. @@ -543,6 +558,9 @@ namespace Slic3r { bool _3MF_Importer::load_model_from_file(const std::string& filename, Model& model, DynamicPrintConfig& config, ConfigSubstitutionContext& config_substitutions, bool check_version) { m_version = 0; + m_fdm_supports_painting_version = 0; + m_seam_painting_version = 0; + m_mm_painting_version = 0; m_check_version = check_version; m_model = &model; m_unit_factor = 1.0f; @@ -1669,6 +1687,12 @@ namespace Slic3r { return true; } + inline static void check_painting_version(unsigned int loaded_version, unsigned int highest_supported_version, const std::string &error_msg) + { + if (loaded_version > highest_supported_version) + throw version_error(error_msg); + } + bool _3MF_Importer::_handle_end_metadata() { if (m_curr_metadata_name == SLIC3RPE_3MF_VERSION) { @@ -1681,6 +1705,24 @@ namespace Slic3r { } } + if (m_curr_metadata_name == SLIC3RPE_FDM_SUPPORTS_PAINTING_VERSION) { + m_fdm_supports_painting_version = (unsigned int) atoi(m_curr_characters.c_str()); + check_painting_version(m_fdm_supports_painting_version, FDM_SUPPORTS_PAINTING_VERSION, + _(L("The selected 3MF contains FDM supports painted object using a newer version of PrusaSlicer and is not compatible."))); + } + + if (m_curr_metadata_name == SLIC3RPE_SEAM_PAINTING_VERSION) { + m_seam_painting_version = (unsigned int) atoi(m_curr_characters.c_str()); + check_painting_version(m_seam_painting_version, SEAM_PAINTING_VERSION, + _(L("The selected 3MF contains seam painted object using a newer version of PrusaSlicer and is not compatible."))); + } + + if (m_curr_metadata_name == SLIC3RPE_MM_PAINTING_VERSION) { + m_mm_painting_version = (unsigned int) atoi(m_curr_characters.c_str()); + check_painting_version(m_mm_painting_version, MM_PAINTING_VERSION, + _(L("The selected 3MF contains multi-material painted object using a newer version of PrusaSlicer and is not compatible."))); + } + return true; } @@ -2294,6 +2336,16 @@ namespace Slic3r { stream << "\n"; stream << "<" << MODEL_TAG << " unit=\"millimeter\" xml:lang=\"en-US\" xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\" xmlns:slic3rpe=\"http://schemas.slic3r.org/3mf/2017/06\">\n"; stream << " <" << METADATA_TAG << " name=\"" << SLIC3RPE_3MF_VERSION << "\">" << VERSION_3MF << "\n"; + + if (model.is_fdm_support_painted()) + stream << " <" << METADATA_TAG << " name=\"" << SLIC3RPE_FDM_SUPPORTS_PAINTING_VERSION << "\">" << FDM_SUPPORTS_PAINTING_VERSION << "\n"; + + if (model.is_seam_painted()) + stream << " <" << METADATA_TAG << " name=\"" << SLIC3RPE_SEAM_PAINTING_VERSION << "\">" << SEAM_PAINTING_VERSION << "\n"; + + if (model.is_mm_painted()) + stream << " <" << METADATA_TAG << " name=\"" << SLIC3RPE_MM_PAINTING_VERSION << "\">" << MM_PAINTING_VERSION << "\n"; + std::string name = xml_escape(boost::filesystem::path(filename).stem().string()); stream << " <" << METADATA_TAG << " name=\"Title\">" << name << "\n"; stream << " <" << METADATA_TAG << " name=\"Designer\">" << "\n"; diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 6f9e4fd4c..dcffbb1f3 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -557,6 +557,21 @@ std::string Model::propose_export_file_name_and_path(const std::string &new_exte return boost::filesystem::path(this->propose_export_file_name_and_path()).replace_extension(new_extension).string(); } +bool Model::is_fdm_support_painted() const +{ + return std::any_of(this->objects.cbegin(), this->objects.cend(), [](const ModelObject *mo) { return mo->is_fdm_support_painted(); }); +} + +bool Model::is_seam_painted() const +{ + return std::any_of(this->objects.cbegin(), this->objects.cend(), [](const ModelObject *mo) { return mo->is_seam_painted(); }); +} + +bool Model::is_mm_painted() const +{ + return std::any_of(this->objects.cbegin(), this->objects.cend(), [](const ModelObject *mo) { return mo->is_mm_painted(); }); +} + ModelObject::~ModelObject() { this->clear_volumes(); @@ -733,6 +748,16 @@ void ModelObject::clear_volumes() this->invalidate_bounding_box(); } +bool ModelObject::is_fdm_support_painted() const +{ + return std::any_of(this->volumes.cbegin(), this->volumes.cend(), [](const ModelVolume *mv) { return mv->is_fdm_support_painted(); }); +} + +bool ModelObject::is_seam_painted() const +{ + return std::any_of(this->volumes.cbegin(), this->volumes.cend(), [](const ModelVolume *mv) { return mv->is_seam_painted(); }); +} + bool ModelObject::is_mm_painted() const { return std::any_of(this->volumes.cbegin(), this->volumes.cend(), [](const ModelVolume *mv) { return mv->is_mm_painted(); }); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index ec6fac821..ba3156139 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -285,6 +285,10 @@ public: void clear_volumes(); void sort_volumes(bool full_sort); bool is_multiparts() const { return volumes.size() > 1; } + // Checks if any of object volume is painted using the fdm support painting gizmo. + bool is_fdm_support_painted() const; + // Checks if any of object volume is painted using the seam painting gizmo. + bool is_seam_painted() const; // Checks if any of object volume is painted using the multi-material painting gizmo. bool is_mm_painted() const; @@ -723,6 +727,8 @@ public: this->mmu_segmentation_facets.set_new_unique_id(); } + bool is_fdm_support_painted() const { return !this->supported_facets.empty(); } + bool is_seam_painted() const { return !this->seam_facets.empty(); } bool is_mm_painted() const { return !this->mmu_segmentation_facets.empty(); } protected: @@ -1127,6 +1133,13 @@ public: // Propose an output path, replace extension. The new_extension shall contain the initial dot. std::string propose_export_file_name_and_path(const std::string &new_extension) const; + // Checks if any of objects is painted using the fdm support painting gizmo. + bool is_fdm_support_painted() const; + // Checks if any of objects is painted using the seam painting gizmo. + bool is_seam_painted() const; + // Checks if any of objects is painted using the multi-material painting gizmo. + bool is_mm_painted() const; + private: explicit Model(int) : ObjectBase(-1) { assert(this->id().invalid()); } void assign_new_unique_ids_recursive(); From b29c0ead7dfc1a997cad012b9f04e84cec1beb9a Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Tue, 31 Aug 2021 16:03:07 +0200 Subject: [PATCH 56/60] Implemented configurable speed and acceleration settings for the first object layer over raft interface: "first_layer_speed_over_raft", "first_layer_acceleration_over_raft". Fixes I have a question about the speed of the first layer after the raft. #6623 Fixes Layer After Raft Is Not Considered First Layer! #6166 --- src/libslic3r/GCode.cpp | 18 +++++++++++++++--- src/libslic3r/GCode.hpp | 11 ++++++++--- src/libslic3r/Preset.cpp | 4 ++-- src/libslic3r/Print.cpp | 2 ++ src/libslic3r/PrintConfig.cpp | 19 +++++++++++++++++++ src/libslic3r/PrintConfig.hpp | 2 ++ src/slic3r/GUI/ConfigManipulation.cpp | 3 ++- src/slic3r/GUI/Tab.cpp | 2 ++ 8 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 85e6f810b..19909b2bc 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1977,6 +1977,7 @@ void GCode::process_layer( } gcode += this->change_layer(print_z); // this will increase m_layer_index m_layer = &layer; + m_object_layer_over_raft = false; if (! print.config().layer_gcode.value.empty()) { DynamicConfig config; config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index)); @@ -2235,8 +2236,13 @@ void GCode::process_layer( gcode+="; PURGING FINISHED\n"; for (InstanceToPrint &instance_to_print : instances_to_print) { + const LayerToPrint &layer_to_print = layers[instance_to_print.layer_id]; + // To control print speed of the 1st object layer printed over raft interface. + bool object_layer_over_raft = layer_to_print.object_layer && layer_to_print.object_layer->id() > 0 && + instance_to_print.print_object.slicing_parameters().raft_layers() == layer_to_print.object_layer->id(); m_config.apply(instance_to_print.print_object.config(), true); - m_layer = layers[instance_to_print.layer_id].layer(); + m_layer = layer_to_print.layer(); + m_object_layer_over_raft = object_layer_over_raft; if (m_config.avoid_crossing_perimeters) m_avoid_crossing_perimeters.init_layer(*m_layer); if (this->config().gcode_label_objects) @@ -2249,11 +2255,13 @@ void GCode::process_layer( m_last_obj_copy = this_object_copy; this->set_origin(unscale(offset)); if (instance_to_print.object_by_extruder.support != nullptr && !print_wipe_extrusions) { - m_layer = layers[instance_to_print.layer_id].support_layer; + m_layer = layer_to_print.support_layer; + m_object_layer_over_raft = false; gcode += this->extrude_support( // support_extrusion_role is erSupportMaterial, erSupportMaterialInterface or erMixed for all extrusion paths. instance_to_print.object_by_extruder.support->chained_path_from(m_last_pos, instance_to_print.object_by_extruder.support_extrusion_role)); - m_layer = layers[instance_to_print.layer_id].layer(); + m_layer = layer_to_print.layer(); + m_object_layer_over_raft = object_layer_over_raft; } //FIXME order islands? // Sequential tool path ordering of multiple parts within the same object, aka. perimeter tracking (#5511) @@ -2705,6 +2713,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, double acceleration; if (this->on_first_layer() && m_config.first_layer_acceleration.value > 0) { acceleration = m_config.first_layer_acceleration.value; + } else if (this->object_layer_over_raft() && m_config.first_layer_acceleration_over_raft.value > 0) { + acceleration = m_config.first_layer_acceleration_over_raft.value; } else if (m_config.perimeter_acceleration.value > 0 && is_perimeter(path.role())) { acceleration = m_config.perimeter_acceleration.value; } else if (m_config.bridge_acceleration.value > 0 && is_bridge(path.role())) { @@ -2749,6 +2759,8 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description, speed = m_volumetric_speed / path.mm3_per_mm; if (this->on_first_layer()) speed = m_config.get_abs_value("first_layer_speed", speed); + else if (this->object_layer_over_raft()) + speed = m_config.get_abs_value("first_layer_speed_over_raft", speed); if (m_config.max_volumetric_speed.value > 0) { // cap speed with max_volumetric_speed anyway (even if user is not using autospeed) speed = std::min( diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 08ab83002..d2d241054 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -125,7 +125,8 @@ public: m_last_processor_extrusion_role(erNone), m_layer_count(0), m_layer_index(-1), - m_layer(nullptr), + m_layer(nullptr), + m_object_layer_over_raft(false), m_volumetric_speed(0), m_last_pos_defined(false), m_last_extrusion_role(erNone), @@ -138,7 +139,7 @@ public: m_silent_time_estimator_enabled(false), m_last_obj_copy(nullptr, Point(std::numeric_limits::max(), std::numeric_limits::max())) {} - ~GCode() {} + ~GCode() = default; // throws std::runtime_exception on error, // throws CanceledException through print->throw_if_canceled(). @@ -316,9 +317,11 @@ private: unsigned int m_layer_count; // Progress bar indicator. Increments from -1 up to layer_count. int m_layer_index; - // Current layer processed. Insequential printing mode, only a single copy will be printed. + // Current layer processed. In sequential printing mode, only a single copy will be printed. // In non-sequential mode, all its copies will be printed. const Layer* m_layer; + // m_layer is an object layer and it is being printed over raft surface. + bool m_object_layer_over_raft; double m_volumetric_speed; // Support for the extrusion role markers. Which marker is active? ExtrusionRole m_last_extrusion_role; @@ -373,6 +376,8 @@ private: void _print_first_layer_extruder_temperatures(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait); // On the first printing layer. This flag triggers first layer speeds. bool on_first_layer() const { return m_layer != nullptr && m_layer->id() == 0; } + // To control print speed of 1st object layer over raft interface. + bool object_layer_over_raft() const { return m_object_layer_over_raft; } friend ObjectByExtruder& object_by_extruder( std::map> &by_extruder, diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 564300baf..f5c8235ed 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -428,8 +428,8 @@ static std::vector s_Preset_print_options { #endif /* HAS_PRESSURE_EQUALIZER */ "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "infill_speed", "solid_infill_speed", "top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed", - "bridge_speed", "gap_fill_speed", "gap_fill_enabled", "travel_speed", "travel_speed_z", "first_layer_speed", "perimeter_acceleration", "infill_acceleration", - "bridge_acceleration", "first_layer_acceleration", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield", + "bridge_speed", "gap_fill_speed", "gap_fill_enabled", "travel_speed", "travel_speed_z", "first_layer_speed", "first_layer_speed_over_raft", "perimeter_acceleration", "infill_acceleration", + "bridge_acceleration", "first_layer_acceleration", "first_layer_acceleration_over_raft", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield", "min_skirt_length", "brim_width", "brim_separation", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers", "raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion", "support_material_pattern", "support_material_with_sheath", "support_material_spacing", "support_material_closing_radius", "support_material_style", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 48737f830..06052a62f 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -88,7 +88,9 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n "filament_cost", "filament_spool_weight", "first_layer_acceleration", + "first_layer_acceleration_over_raft", "first_layer_bed_temperature", + "first_layer_speed_over_raft", "gcode_comments", "gcode_label_objects", "infill_acceleration", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index b5c1cbeb3..2917a9a19 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -1152,6 +1152,15 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->set_default_value(new ConfigOptionFloat(0)); + def = this->add("first_layer_acceleration_over_raft", coFloat); + def->label = L("First object layer over raft interface"); + def->tooltip = L("This is the acceleration your printer will use for first layer of object above raft interface. Set zero " + "to disable acceleration control for first layer of object above raft interface."); + def->sidetext = L("mm/s²"); + def->min = 0; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloat(0)); + def = this->add("first_layer_bed_temperature", coInts); def->label = L("First layer"); def->full_label = L("First layer bed temperature"); @@ -1194,6 +1203,16 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloatOrPercent(30, false)); + def = this->add("first_layer_speed_over_raft", coFloatOrPercent); + def->label = L("Speed of object first layer over raft interface"); + def->tooltip = L("If expressed as absolute value in mm/s, this speed will be applied to all the print moves " + "of the first object layer above raft interface, regardless of their type. If expressed as a percentage " + "(for example: 40%) it will scale the default speeds."); + def->sidetext = L("mm/s or %"); + def->min = 0; + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionFloatOrPercent(30, false)); + def = this->add("first_layer_temperature", coInts); def->label = L("First layer"); def->full_label = L("First layer nozzle temperature"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index f5070c54d..d7409d12c 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -456,6 +456,8 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionBool, dont_support_bridges)) ((ConfigOptionFloat, elefant_foot_compensation)) ((ConfigOptionFloatOrPercent, extrusion_width)) + ((ConfigOptionFloat, first_layer_acceleration_over_raft)) + ((ConfigOptionFloatOrPercent, first_layer_speed_over_raft)) ((ConfigOptionBool, infill_only_where_needed)) // Force the generation of solid shells between adjacent materials/volumes. ((ConfigOptionBool, interface_shells)) diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 72584e938..d4920d836 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -312,7 +312,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) toggle_field("support_material_speed", have_support_material || have_brim || have_skirt); toggle_field("raft_contact_distance", have_raft && !have_support_soluble); - toggle_field("raft_expansion", have_raft); + for (auto el : { "raft_expansion", "first_layer_acceleration_over_raft", "first_layer_speed_over_raft" }) + toggle_field(el, have_raft); bool has_ironing = config->opt_bool("ironing"); for (auto el : { "ironing_type", "ironing_flowrate", "ironing_spacing", "ironing_speed" }) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 6bd295fdc..86089f729 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1565,12 +1565,14 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Modifiers")); optgroup->append_single_option_line("first_layer_speed"); + optgroup->append_single_option_line("first_layer_speed_over_raft"); optgroup = page->new_optgroup(L("Acceleration control (advanced)")); optgroup->append_single_option_line("perimeter_acceleration"); optgroup->append_single_option_line("infill_acceleration"); optgroup->append_single_option_line("bridge_acceleration"); optgroup->append_single_option_line("first_layer_acceleration"); + optgroup->append_single_option_line("first_layer_acceleration_over_raft"); optgroup->append_single_option_line("default_acceleration"); optgroup = page->new_optgroup(L("Autospeed (advanced)")); From d7bb4c36f58dfb46834919a6625ea7637f374954 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 1 Sep 2021 09:34:07 +0200 Subject: [PATCH 57/60] Requires OpenGL 3.3 as a minimum to enable instanced rendering of seams and other options in preview --- src/slic3r/GUI/GCodeViewer.cpp | 2 +- src/slic3r/GUI/GLShadersManager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 732403b03..ad2e6e973 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -807,7 +807,7 @@ void GCodeViewer::render() case EMoveType::Unretract: case EMoveType::Seam: { #if ENABLE_SEAMS_USING_MODELS - if (wxGetApp().is_gl_version_greater_or_equal_to(3, 1)) { + if (wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) { buffer.render_primitive_type = TBuffer::ERenderPrimitiveType::Model; buffer.shader = "gouraud_light_instanced"; buffer.model.model.init_from(diamond(16)); diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index c93f22f46..edbe2bb46 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -39,7 +39,7 @@ std::pair GLShadersManager::init() valid &= append_shader("printbed", { "printbed.vs", "printbed.fs" }); // used to render options in gcode preview #if ENABLE_SEAMS_USING_MODELS - if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 1)) + if (GUI::wxGetApp().is_gl_version_greater_or_equal_to(3, 3)) valid &= append_shader("gouraud_light_instanced", { "gouraud_light_instanced.vs", "gouraud_light_instanced.fs" }); else { #endif // ENABLE_SEAMS_USING_MODELS From 95c05aae3bb85b9da51e466578a0061c23e7881d Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 1 Sep 2021 09:54:59 +0200 Subject: [PATCH 58/60] Fixed typo which broke export of toolpaths to obj file --- src/slic3r/GUI/GCodeViewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index ad2e6e973..e6e391d37 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1100,7 +1100,7 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const // save vertices to file fprintf(fp, "\n# vertices\n"); for (const Vec3f& v : out_vertices) { - fprintf(fp, "v %g %g %g\n", v.x(), v.y(), v.x()); + fprintf(fp, "v %g %g %g\n", v.x(), v.y(), v.z()); } // save normals to file From ab84da6c56767d9894eea925263966bdefdf0556 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Wed, 1 Sep 2021 11:08:08 +0200 Subject: [PATCH 59/60] Fix for #6803 - Illegal character in filename when STL opened direct from CAD app Follow-up to ea4e9b35a3e2084325fbaed4c5bedf310bcdef3e Win32 specific: Substitute slashes to back slashes in file paths when loading model files (STLs, 3MFS ...) --- src/slic3r/GUI/GUI_ObjectList.cpp | 3 +-- src/slic3r/GUI/Plater.cpp | 36 +++++++++++++------------------ 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 82f03f51a..737c84083 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -1702,8 +1702,7 @@ void ObjectList::load_shape_object_from_gallery(const wxArrayString& input_files snapshot_label += ", " + wxString::FromUTF8(paths[i].filename().string().c_str()); take_snapshot(snapshot_label); - std::vector res = wxGetApp().plater()->load_files(paths, true, false); - if (!res.empty()) + if (! wxGetApp().plater()->load_files(paths, true, false).empty()) wxGetApp().mainframe->update_title(); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 743f27578..98eb73c89 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2221,7 +2221,14 @@ std::vector Plater::priv::load_files(const std::vector& input_ std::vector obj_idxs; for (size_t i = 0; i < input_files.size(); ++i) { +#ifdef _WIN32 + auto path = input_files[i]; + // On Windows, we swap slashes to back slashes, see GH #6803 as read_from_file() does not understand slashes on Windows thus it assignes full path to names of loaded objects. + path.make_preferred(); +#else // _WIN32 + // Don't make a copy on Posix. Slash is a path separator, back slashes are not accepted as a substitute. const auto &path = input_files[i]; +#endif // _WIN32 const auto filename = path.filename(); dlg.Update(static_cast(100.0f * static_cast(i) / static_cast(input_files.size())), _L("Loading file") + ": " + from_path(filename)); dlg.Fit(); @@ -2336,9 +2343,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ else { model = Slic3r::Model::read_from_file(path.string(), nullptr, nullptr, only_if(load_config, Model::LoadAttribute::CheckVersion)); for (auto obj : model.objects) - if (obj->name.empty() || - obj->name.find_first_of("/") != std::string::npos) // When file is imported from Fusion360 the path containes "/" instead of "\\" (see https://github.com/prusa3d/PrusaSlicer/issues/6803) - // But read_from_file doesn't support that direction separator and as a result object name containes full path + if (obj->name.empty()) obj->name = fs::path(obj->input_file).filename().string(); } } catch (const ConfigurationError &e) { @@ -2457,7 +2462,7 @@ std::vector Plater::priv::load_files(const std::vector& input_ } if (load_model) { - wxGetApp().app_config->update_skein_dir(input_files[input_files.size() - 1].parent_path().string()); + wxGetApp().app_config->update_skein_dir(input_files[input_files.size() - 1].parent_path().make_preferred().string()); // XXX: Plater.pm had @loaded_files, but didn't seem to fill them with the filenames... statusbar()->set_status_text(_L("Loaded")); } @@ -4787,10 +4792,7 @@ void Plater::load_project(const wxString& filename) p->reset(); - std::vector input_paths; - input_paths.push_back(into_path(filename)); - - if (! load_files(input_paths).empty()) { + if (! load_files({ into_path(filename) }).empty()) { // At least one file was loaded. p->set_project_filename(filename); reset_project_dirty_initial_presets(); @@ -4807,7 +4809,7 @@ void Plater::add_model(bool imperial_units/* = false*/) std::vector paths; for (const auto &file : input_files) - paths.push_back(into_path(file)); + paths.emplace_back(into_path(file)); wxString snapshot_label; assert(! paths.empty()); @@ -4840,12 +4842,8 @@ void Plater::extract_config_from_project() wxString input_file; wxGetApp().load_project(this, input_file); - if (input_file.empty()) - return; - - std::vector input_paths; - input_paths.push_back(into_path(input_file)); - load_files(input_paths, false, true); + if (! input_file.empty()) + load_files({ into_path(input_file) }, false, true); } void Plater::load_gcode() @@ -5076,15 +5074,11 @@ bool Plater::load_files(const wxArrayString& filenames) } case LoadType::LoadGeometry: { Plater::TakeSnapshot snapshot(this, _L("Import Object")); - std::vector in_paths; - in_paths.emplace_back(*it); - load_files(in_paths, true, false); + load_files({ *it }, true, false); break; } case LoadType::LoadConfig: { - std::vector in_paths; - in_paths.emplace_back(*it); - load_files(in_paths, false, true); + load_files({ *it }, false, true); break; } case LoadType::Unknown : { From 73e8f5aed2cccb17c6dee29bd91f6636882be7a4 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 1 Sep 2021 12:58:25 +0200 Subject: [PATCH 60/60] Supress desktop integration of gcode viewer at ChromeOS --- src/slic3r/GUI/DesktopIntegrationDialog.cpp | 91 +++++++++++---------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/src/slic3r/GUI/DesktopIntegrationDialog.cpp b/src/slic3r/GUI/DesktopIntegrationDialog.cpp index 935121935..24552ec58 100644 --- a/src/slic3r/GUI/DesktopIntegrationDialog.cpp +++ b/src/slic3r/GUI/DesktopIntegrationDialog.cpp @@ -382,40 +382,44 @@ void DesktopIntegrationDialog::perform_desktop_integration() app_config->set("desktop_integration_app_path", GUI::format("%1%/applications/PrusaSlicer%2%.desktop", target_dir_desktop, version_suffix)); // Repeat for Gcode viewer - use same paths as for slicer files - // Icon - if (!target_dir_icons.empty()) - { - std::string icon_path = GUI::format("%1%/icons/PrusaSlicer-gcodeviewer_192px.png",resources_dir()); - std::string dest_path = GUI::format("%1%/icons/%2%PrusaSlicer-gcodeviewer%3%.png", target_dir_icons, icon_theme_path, version_suffix); - if (copy_icon(icon_path, dest_path)) - // save path to icon - app_config->set("desktop_integration_icon_viewer_path", dest_path); - else - BOOST_LOG_TRIVIAL(error) << "Copying Gcode Viewer icon to icons directory failed."; - } + // Do NOT add gcode viewer desktop file on ChromeOS + if (platform_flavor() != PlatformFlavor::LinuxOnChromium) { + // Icon + if (!target_dir_icons.empty()) + { + std::string icon_path = GUI::format("%1%/icons/PrusaSlicer-gcodeviewer_192px.png",resources_dir()); + std::string dest_path = GUI::format("%1%/icons/%2%PrusaSlicer-gcodeviewer%3%.png", target_dir_icons, icon_theme_path, version_suffix); + if (copy_icon(icon_path, dest_path)) + // save path to icon + app_config->set("desktop_integration_icon_viewer_path", dest_path); + else + BOOST_LOG_TRIVIAL(error) << "Copying Gcode Viewer icon to icons directory failed."; + } - // Desktop file - std::string desktop_file = GUI::format( - "[Desktop Entry]\n" - "Name=Prusa Gcode Viewer%1%\n" - "GenericName=3D Printing Software\n" - "Icon=PrusaSlicer-gcodeviewer%2%\n" - "Exec=\"%3%\" --gcodeviewer %%F\n" - "Terminal=false\n" - "Type=Application\n" - "MimeType=text/x.gcode;\n" - "Categories=Graphics;3DGraphics;\n" - "Keywords=3D;Printing;Slicer;\n" - "StartupNotify=false\n", name_suffix, version_suffix, excutable_path); + // Desktop file + std::string desktop_file = GUI::format( + "[Desktop Entry]\n" + "Name=Prusa Gcode Viewer%1%\n" + "GenericName=3D Printing Software\n" + "Icon=PrusaSlicer-gcodeviewer%2%\n" + "Exec=\"%3%\" --gcodeviewer %%F\n" + "Terminal=false\n" + "Type=Application\n" + "MimeType=text/x.gcode;\n" + "Categories=Graphics;3DGraphics;\n" + "Keywords=3D;Printing;Slicer;\n" + "StartupNotify=false\n", name_suffix, version_suffix, excutable_path); - std::string desktop_path = GUI::format("%1%/applications/PrusaSlicerGcodeViewer%2%.desktop", target_dir_desktop, version_suffix); - if (create_desktop_file(desktop_path, desktop_file)) - // save path to desktop file - app_config->set("desktop_integration_app_viewer_path", desktop_path); - else { - BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - could not create Gcodeviewer desktop file"; - show_error(nullptr, _L("Performing desktop integration failed - could not create Gcodeviewer desktop file. PrusaSlicer desktop file was probably created successfully.")); + std::string desktop_path = GUI::format("%1%/applications/PrusaSlicerGcodeViewer%2%.desktop", target_dir_desktop, version_suffix); + if (create_desktop_file(desktop_path, desktop_file)) + // save path to desktop file + app_config->set("desktop_integration_app_viewer_path", desktop_path); + else { + BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - could not create Gcodeviewer desktop file"; + show_error(nullptr, _L("Performing desktop integration failed - could not create Gcodeviewer desktop file. PrusaSlicer desktop file was probably created successfully.")); + } } + wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::DesktopIntegrationSuccess); } void DesktopIntegrationDialog::undo_desktop_intgration() @@ -433,17 +437,20 @@ void DesktopIntegrationDialog::undo_desktop_intgration() BOOST_LOG_TRIVIAL(debug) << "removing " << path; std::remove(path.c_str()); } - // gcode viwer .desktop - path = std::string(app_config->get("desktop_integration_app_viewer_path")); - if (!path.empty()) { - BOOST_LOG_TRIVIAL(debug) << "removing " << path; - std::remove(path.c_str()); - } - // gcode viewer icon - path = std::string(app_config->get("desktop_integration_icon_viewer_path")); - if (!path.empty()) { - BOOST_LOG_TRIVIAL(debug) << "removing " << path; - std::remove(path.c_str()); + // No gcode viewer at ChromeOS + if (platform_flavor() != PlatformFlavor::LinuxOnChromium) { + // gcode viewer .desktop + path = std::string(app_config->get("desktop_integration_app_viewer_path")); + if (!path.empty()) { + BOOST_LOG_TRIVIAL(debug) << "removing " << path; + std::remove(path.c_str()); + } + // gcode viewer icon + path = std::string(app_config->get("desktop_integration_icon_viewer_path")); + if (!path.empty()) { + BOOST_LOG_TRIVIAL(debug) << "removing " << path; + std::remove(path.c_str()); + } } wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::UndoDesktopIntegrationSuccess); }