From bc05ab985c278af18590730f7c253caa332c618b Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 14 Apr 2020 16:40:08 +0200 Subject: [PATCH] GCodeViewer -> Toggle visibility of travel paths, retractions and uretractions --- resources/shaders/retractions.vs | 2 + resources/shaders/toolchanges.vs | 2 + resources/shaders/unretractions.vs | 2 + src/slic3r/GUI/GCodeViewer.cpp | 121 ++++++++++++++++++++++------- src/slic3r/GUI/GCodeViewer.hpp | 36 ++++----- src/slic3r/GUI/GLCanvas3D.cpp | 34 ++++++-- src/slic3r/GUI/GLCanvas3D.hpp | 9 +++ src/slic3r/GUI/GUI_Preview.cpp | 20 +++++ 8 files changed, 173 insertions(+), 53 deletions(-) diff --git a/resources/shaders/retractions.vs b/resources/shaders/retractions.vs index d97adbabe..ba1807335 100644 --- a/resources/shaders/retractions.vs +++ b/resources/shaders/retractions.vs @@ -12,4 +12,6 @@ void main() // eye_normal = gl_NormalMatrix * gl_Normal; // world_normal_z = gl_Normal.z; gl_Position = ftransform(); + + gl_PointSize = 3.0; } diff --git a/resources/shaders/toolchanges.vs b/resources/shaders/toolchanges.vs index d97adbabe..ba1807335 100644 --- a/resources/shaders/toolchanges.vs +++ b/resources/shaders/toolchanges.vs @@ -12,4 +12,6 @@ void main() // eye_normal = gl_NormalMatrix * gl_Normal; // world_normal_z = gl_Normal.z; gl_Position = ftransform(); + + gl_PointSize = 3.0; } diff --git a/resources/shaders/unretractions.vs b/resources/shaders/unretractions.vs index d97adbabe..ba1807335 100644 --- a/resources/shaders/unretractions.vs +++ b/resources/shaders/unretractions.vs @@ -12,4 +12,6 @@ void main() // eye_normal = gl_NormalMatrix * gl_Normal; // world_normal_z = gl_Normal.z; gl_Position = ftransform(); + + gl_PointSize = 3.0; } diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 584ef06c3..00567eab6 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -8,6 +8,8 @@ #include #include +#include +#include namespace Slic3r { namespace GUI { @@ -20,15 +22,27 @@ static GCodeProcessor::EMoveType buffer_type(unsigned char id) { return static_cast(static_cast(GCodeProcessor::EMoveType::Retract) + id); } +void GCodeViewer::Buffer::reset() +{ + // release gpu memory + if (vbo_id > 0) + glsafe(::glDeleteBuffers(1, &vbo_id)); + + // release cpu memory + data = std::vector(); +} + void GCodeViewer::generate(const GCodeProcessor::Result& gcode_result) { if (m_last_result_id == gcode_result.id) return; + auto start_time = std::chrono::high_resolution_clock::now(); + m_last_result_id = gcode_result.id; // release gpu memory, if used - reset_buffers(); + reset(); // convert data size_t vertices_count = gcode_result.moves.size(); @@ -73,16 +87,49 @@ void GCodeViewer::generate(const GCodeProcessor::Result& gcode_result) continue; } } + if (curr.type == GCodeProcessor::EMoveType::Extrude) + m_layers_zs.emplace_back(curr.position[2]); } + std::sort(m_layers_zs.begin(), m_layers_zs.end()); + + // Replace intervals of layers with similar top positions with their average value. + int n = int(m_layers_zs.size()); + int k = 0; + for (int i = 0; i < n;) { + int j = i + 1; + double zmax = m_layers_zs[i] + EPSILON; + for (; j < n && m_layers_zs[j] <= zmax; ++j); + m_layers_zs[k++] = (j > i + 1) ? (0.5 * (m_layers_zs[i] + m_layers_zs[j - 1])) : m_layers_zs[i]; + i = j; + } + if (k < n) + m_layers_zs.erase(m_layers_zs.begin() + k, m_layers_zs.end()); + // send data to gpu for (Buffer& buffer : m_buffers) { - glsafe(::glGenBuffers(1, &buffer.vbo_id)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, buffer.vbo_id)); - glsafe(::glBufferData(GL_ARRAY_BUFFER, buffer.data.size() * sizeof(float), buffer.data.data(), GL_STATIC_DRAW)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + if (buffer.data.size() > 0) + { + glsafe(::glGenBuffers(1, &buffer.vbo_id)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, buffer.vbo_id)); + glsafe(::glBufferData(GL_ARRAY_BUFFER, buffer.data.size() * sizeof(float), buffer.data.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + } } + + auto end_time = std::chrono::high_resolution_clock::now(); + std::cout << "toolpaths generation time: " << std::chrono::duration_cast(end_time - start_time).count() << "ms \n"; +} + +void GCodeViewer::reset() +{ + for (Buffer& buffer : m_buffers) + { + buffer.reset(); + } + + m_layers_zs = std::vector(); } void GCodeViewer::render() const @@ -111,10 +158,12 @@ void GCodeViewer::render() const if (buffer.vbo_id == 0) continue; - const Shader& shader = m_shaders[i]; - if (shader.is_initialized()) + if (!buffer.visible) + continue; + + if (buffer.shader.is_initialized()) { - shader.start_using(); + buffer.shader.start_using(); GLint current_program_id; glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id)); @@ -122,32 +171,50 @@ void GCodeViewer::render() const GCodeProcessor::EMoveType type = buffer_type(i); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, buffer.vbo_id)); - glsafe(::glVertexPointer(3, GL_FLOAT, Buffer::stride(type), (const void*)0)); + glsafe(::glVertexPointer(3, GL_FLOAT, Buffer::vertex_size_bytes(), (const void*)0)); glsafe(::glEnableClientState(GL_VERTEX_ARRAY)); switch (type) { case GCodeProcessor::EMoveType::Tool_change: + { + std::array color = { 1.0f, 1.0f, 1.0f, 1.0f }; + set_color(current_program_id, color); + glsafe(::glEnable(GL_PROGRAM_POINT_SIZE)); + glsafe(::glDrawArrays(GL_POINTS, 0, (GLsizei)buffer.data.size() / Buffer::vertex_size())); + glsafe(::glDisable(GL_PROGRAM_POINT_SIZE)); + break; + } case GCodeProcessor::EMoveType::Retract: + { + std::array color = { 1.0f, 0.0f, 1.0f, 1.0f }; + set_color(current_program_id, color); + glsafe(::glEnable(GL_PROGRAM_POINT_SIZE)); + glsafe(::glDrawArrays(GL_POINTS, 0, (GLsizei)buffer.data.size() / Buffer::vertex_size())); + glsafe(::glDisable(GL_PROGRAM_POINT_SIZE)); + break; + } case GCodeProcessor::EMoveType::Unretract: { std::array color = { 0.0f, 1.0f, 0.0f, 1.0f }; set_color(current_program_id, color); - glsafe(::glDrawArrays(GL_POINTS, 0, (GLsizei)buffer.data.size() / Buffer::record_size(type))); + glsafe(::glEnable(GL_PROGRAM_POINT_SIZE)); + glsafe(::glDrawArrays(GL_POINTS, 0, (GLsizei)buffer.data.size() / Buffer::vertex_size())); + glsafe(::glDisable(GL_PROGRAM_POINT_SIZE)); break; } case GCodeProcessor::EMoveType::Extrude: { std::array color = { 1.0f, 0.0f, 0.0f, 1.0f }; set_color(current_program_id, color); - glsafe(::glDrawArrays(GL_LINES, 0, (GLsizei)buffer.data.size() / Buffer::record_size(type))); + glsafe(::glDrawArrays(GL_LINES, 0, (GLsizei)buffer.data.size() / Buffer::vertex_size())); break; } case GCodeProcessor::EMoveType::Travel: { std::array color = { 1.0f, 1.0f, 0.0f, 1.0f }; set_color(current_program_id, color); - glsafe(::glDrawArrays(GL_LINES, 0, (GLsizei)buffer.data.size() / Buffer::record_size(type))); + glsafe(::glDrawArrays(GL_LINES, 0, (GLsizei)buffer.data.size() / Buffer::vertex_size())); break; } default: @@ -159,11 +226,24 @@ void GCodeViewer::render() const glsafe(::glDisableClientState(GL_VERTEX_ARRAY)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); - shader.stop_using(); + buffer.shader.stop_using(); } } } +bool GCodeViewer::is_toolpath_visible(GCodeProcessor::EMoveType type) const +{ + size_t id = static_cast(buffer_id(type)); + return (id < m_buffers.size()) ? m_buffers[id].visible : false; +} + +void GCodeViewer::set_toolpath_visible(GCodeProcessor::EMoveType type, bool visible) +{ + size_t id = static_cast(buffer_id(type)); + if (id < m_buffers.size()) + m_buffers[id].visible = visible; +} + bool GCodeViewer::init_shaders() { unsigned char begin_id = buffer_id(GCodeProcessor::EMoveType::Retract); @@ -171,7 +251,7 @@ bool GCodeViewer::init_shaders() for (unsigned char i = begin_id; i < end_id; ++i) { - Shader& shader = m_shaders[i]; + Shader& shader = m_buffers[i].shader; std::string vertex_shader_src; std::string fragment_shader_src; GCodeProcessor::EMoveType type = buffer_type(i); @@ -223,19 +303,6 @@ bool GCodeViewer::init_shaders() return true; } -void GCodeViewer::reset_buffers() -{ - for (Buffer& buffer : m_buffers) - { - // release gpu memory - if (buffer.vbo_id > 0) - glsafe(::glDeleteBuffers(1, &buffer.vbo_id)); - - // release cpu memory - buffer.data = std::vector(); - } -} - } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 95250b203..0ed5c337c 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -16,42 +16,38 @@ class GCodeViewer struct Buffer { unsigned int vbo_id{ 0 }; + Shader shader; std::vector data; + bool visible{ false }; - static size_t stride(GCodeProcessor::EMoveType type) - { - return 3 * sizeof(float); - } + void reset(); - static size_t record_size(GCodeProcessor::EMoveType type) - { - switch (type) - { - case GCodeProcessor::EMoveType::Tool_change: - case GCodeProcessor::EMoveType::Retract: - case GCodeProcessor::EMoveType::Unretract: { return 3; } - case GCodeProcessor::EMoveType::Extrude: - case GCodeProcessor::EMoveType::Travel: { return 6; } - default: { return 0; } - } - } + static size_t vertex_size() { return 3; } + + static size_t vertex_size_bytes() { return vertex_size() * sizeof(float); } }; std::vector m_buffers{ static_cast(GCodeProcessor::EMoveType::Extrude) }; - std::vector m_shaders{ static_cast(GCodeProcessor::EMoveType::Extrude) }; + unsigned int m_last_result_id{ 0 }; + std::vector m_layers_zs; public: GCodeViewer() = default; - ~GCodeViewer() { reset_buffers(); } + ~GCodeViewer() { reset(); } - bool init() { return init_shaders(); } + bool init() { set_toolpath_visible(GCodeProcessor::EMoveType::Extrude, true); return init_shaders(); } void generate(const GCodeProcessor::Result& gcode_result); + void reset(); void render() const; + const std::vector& get_layers_zs() const { return m_layers_zs; }; + + bool is_toolpath_visible(GCodeProcessor::EMoveType type) const; + void set_toolpath_visible(GCodeProcessor::EMoveType type, bool visible); + private: bool init_shaders(); - void reset_buffers(); }; } // namespace GUI diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index c9c4ab336..66120668c 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -932,7 +932,11 @@ void GLCanvas3D::LegendTexture::fill_color_print_legend_items( const GLCanvas3D std::vector> cp_values; cp_values.reserve(custom_gcode_per_print_z.size()); +#if ENABLE_GCODE_VIEWER + const std::vector& print_zs = canvas.get_layers_zs(); +#else std::vector print_zs = canvas.get_current_print_zs(true); +#endif // ENABLE_GCODE_VIEWER for (auto custom_code : custom_gcode_per_print_z) { if (custom_code.gcode != ColorChangeCode) @@ -2303,10 +2307,23 @@ void GLCanvas3D::ensure_on_bed(unsigned int object_idx) } } + +#if ENABLE_GCODE_VIEWER +const std::vector& GLCanvas3D::get_layers_zs() const +{ + return m_gcode_viewer.get_layers_zs(); +} + +void GLCanvas3D::set_toolpath_visible(GCodeProcessor::EMoveType type, bool visible) +{ + m_gcode_viewer.set_toolpath_visible(type, visible); +} +#else std::vector GLCanvas3D::get_current_print_zs(bool active_only) const { return m_volumes.get_current_print_zs(active_only); } +#endif // ENABLE_GCODE_VIEWER void GLCanvas3D::set_toolpaths_range(double low, double high) { @@ -2786,14 +2803,19 @@ static void load_gcode_retractions(const GCodePreviewData::Retraction& retractio void GLCanvas3D::load_gcode_preview_2(const GCodeProcessor::Result& gcode_result) { #if ENABLE_GCODE_VIEWER_DEBUG_OUTPUT - boost::filesystem::path path("d:/processor.output"); - boost::nowide::ofstream out; - out.open(path.string()); - for (const GCodeProcessor::MoveVertex& v : gcode_result.moves) + static unsigned int last_result_id = 0; + if (last_result_id != gcode_result.id) { - out << v.to_string() << "\n"; + last_result_id = gcode_result.id; + boost::filesystem::path path("d:/processor.output"); + boost::nowide::ofstream out; + out.open(path.string()); + for (const GCodeProcessor::MoveVertex& v : gcode_result.moves) + { + out << v.to_string() << "\n"; + } + out.close(); } - out.close(); m_gcode_viewer.generate(gcode_result); #endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 8c6b3c3f0..592c85c03 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -549,6 +549,10 @@ public: void reset_volumes(); int check_volumes_outside_state() const; +#if ENABLE_GCODE_VIEWER + void reset_gcode_toolpaths() { m_gcode_viewer.reset(); } +#endif // ENABLE_GCODE_VIEWER + void toggle_sla_auxiliaries_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1); void toggle_model_objects_visibility(bool visible, const ModelObject* mo = nullptr, int instance_idx = -1); void update_instance_printable_state_for_object(size_t obj_idx); @@ -635,7 +639,12 @@ public: void delete_selected(); void ensure_on_bed(unsigned int object_idx); +#if ENABLE_GCODE_VIEWER + const std::vector& get_layers_zs() const; + void set_toolpath_visible(GCodeProcessor::EMoveType type, bool visible); +#else std::vector get_current_print_zs(bool active_only) const; +#endif // ENABLE_GCODE_VIEWER void set_toolpaths_range(double low, double high); std::vector load_object(const ModelObject& model_object, int obj_idx, std::vector instance_idxs); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 0171dd597..2e0c71268 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -474,6 +474,9 @@ void Preview::reload_print(bool keep_volumes) !keep_volumes) { m_canvas->reset_volumes(); +#if ENABLE_GCODE_VIEWER + m_canvas->reset_gcode_toolpaths(); +#endif // ENABLE_GCODE_VIEWER m_canvas->reset_legend_texture(); m_loaded = false; #ifdef __linux__ @@ -614,21 +617,34 @@ void Preview::on_combochecklist_features(wxCommandEvent& evt) void Preview::on_checkbox_travel(wxCommandEvent& evt) { +#if ENABLE_GCODE_VIEWER + m_canvas->set_toolpath_visible(GCodeProcessor::EMoveType::Travel, m_checkbox_travel->IsChecked()); + refresh_print(); +#else m_gcode_preview_data->travel.is_visible = m_checkbox_travel->IsChecked(); m_gcode_preview_data->ranges.feedrate.set_mode(GCodePreviewData::FeedrateKind::TRAVEL, m_gcode_preview_data->travel.is_visible); // Rather than refresh, reload print so that speed color ranges get recomputed (affected by travel visibility) reload_print(); +#endif // ENABLE_GCODE_VIEWER } void Preview::on_checkbox_retractions(wxCommandEvent& evt) { +#if ENABLE_GCODE_VIEWER + m_canvas->set_toolpath_visible(GCodeProcessor::EMoveType::Retract, m_checkbox_retractions->IsChecked()); +#else m_gcode_preview_data->retraction.is_visible = m_checkbox_retractions->IsChecked(); +#endif // ENABLE_GCODE_VIEWER refresh_print(); } void Preview::on_checkbox_unretractions(wxCommandEvent& evt) { +#if ENABLE_GCODE_VIEWER + m_canvas->set_toolpath_visible(GCodeProcessor::EMoveType::Unretract, m_checkbox_unretractions->IsChecked()); +#else m_gcode_preview_data->unretraction.is_visible = m_checkbox_unretractions->IsChecked(); +#endif // ENABLE_GCODE_VIEWER refresh_print(); } @@ -958,7 +974,11 @@ void Preview::load_print_as_fff(bool keep_z_range) } show_hide_ui_elements(gcode_preview_data_valid ? "full" : "simple"); // recalculates zs and update sliders accordingly +#if ENABLE_GCODE_VIEWER + const std::vector& zs = m_canvas->get_layers_zs(); +#else std::vector zs = m_canvas->get_current_print_zs(true); +#endif // ENABLE_GCODE_VIEWER if (zs.empty()) { // all layers filtered out reset_sliders(true);