GCodeViewer -> Toggle visibility of travel paths, retractions and uretractions
This commit is contained in:
parent
c3eb65c461
commit
bc05ab985c
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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, ¤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<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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user