GCodeViewer -> Toggle visibility of travel paths, retractions and uretractions

This commit is contained in:
enricoturri1966 2020-04-14 16:40:08 +02:00
parent c3eb65c461
commit bc05ab985c
8 changed files with 173 additions and 53 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -8,6 +8,8 @@
#include <boost/log/trivial.hpp>
#include <array>
#include <algorithm>
#include <chrono>
namespace Slic3r {
namespace GUI {
@ -20,15 +22,27 @@ static GCodeProcessor::EMoveType buffer_type(unsigned char id) {
return static_cast<GCodeProcessor::EMoveType>(static_cast<unsigned char>(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<float>();
}
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<std::chrono::milliseconds>(end_time - start_time).count() << "ms \n";
}
void GCodeViewer::reset()
{
for (Buffer& buffer : m_buffers)
{
buffer.reset();
}
m_layers_zs = std::vector<double>();
}
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, &current_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<float, 4> 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<float, 4> 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<float, 4> 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<float, 4> 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<float, 4> 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<size_t>(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<size_t>(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<float>();
}
}
} // namespace GUI
} // namespace Slic3r

View File

@ -16,42 +16,38 @@ class GCodeViewer
struct Buffer
{
unsigned int vbo_id{ 0 };
Shader shader;
std::vector<float> 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<Buffer> m_buffers{ static_cast<size_t>(GCodeProcessor::EMoveType::Extrude) };
std::vector<Shader> m_shaders{ static_cast<size_t>(GCodeProcessor::EMoveType::Extrude) };
unsigned int m_last_result_id{ 0 };
std::vector<double> 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<double>& 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

View File

@ -932,7 +932,11 @@ void GLCanvas3D::LegendTexture::fill_color_print_legend_items( const GLCanvas3D
std::vector<std::pair<double, double>> cp_values;
cp_values.reserve(custom_gcode_per_print_z.size());
#if ENABLE_GCODE_VIEWER
const std::vector<double>& print_zs = canvas.get_layers_zs();
#else
std::vector<double> 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<double>& 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<double> 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

View File

@ -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<double>& get_layers_zs() const;
void set_toolpath_visible(GCodeProcessor::EMoveType type, bool visible);
#else
std::vector<double> get_current_print_zs(bool active_only) const;
#endif // ENABLE_GCODE_VIEWER
void set_toolpaths_range(double low, double high);
std::vector<int> load_object(const ModelObject& model_object, int obj_idx, std::vector<int> instance_idxs);

View File

@ -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<double>& zs = m_canvas->get_layers_zs();
#else
std::vector<double> zs = m_canvas->get_current_print_zs(true);
#endif // ENABLE_GCODE_VIEWER
if (zs.empty()) {
// all layers filtered out
reset_sliders(true);