2020-04-14 08:02:08 +00:00
|
|
|
#ifndef slic3r_GCodeViewer_hpp_
|
|
|
|
#define slic3r_GCodeViewer_hpp_
|
|
|
|
|
|
|
|
#if ENABLE_GCODE_VIEWER
|
|
|
|
|
|
|
|
#include "GLShader.hpp"
|
2020-04-15 12:31:39 +00:00
|
|
|
#include "3DScene.hpp"
|
2020-04-14 08:02:08 +00:00
|
|
|
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
|
|
|
|
2020-04-20 08:52:16 +00:00
|
|
|
#include <float.h>
|
|
|
|
|
2020-04-14 08:02:08 +00:00
|
|
|
namespace Slic3r {
|
2020-04-15 12:31:39 +00:00
|
|
|
class Print;
|
2020-04-14 08:02:08 +00:00
|
|
|
namespace GUI {
|
|
|
|
|
|
|
|
class GCodeViewer
|
|
|
|
{
|
2020-04-22 14:29:07 +00:00
|
|
|
static const std::vector<std::array<float, 3>> Extrusion_Role_Colors;
|
2020-04-24 06:46:31 +00:00
|
|
|
static const std::vector<std::array<float, 3>> Travel_Colors;
|
2020-04-22 14:29:07 +00:00
|
|
|
static const std::vector<std::array<float, 3>> Range_Colors;
|
2020-04-16 13:09:04 +00:00
|
|
|
|
2020-04-15 14:29:11 +00:00
|
|
|
// buffer containing vertices data
|
|
|
|
struct VBuffer
|
2020-04-14 08:02:08 +00:00
|
|
|
{
|
|
|
|
unsigned int vbo_id{ 0 };
|
2020-04-15 14:29:11 +00:00
|
|
|
size_t vertices_count{ 0 };
|
|
|
|
|
|
|
|
size_t data_size_bytes() { return vertices_count * vertex_size_bytes(); }
|
2020-04-14 08:02:08 +00:00
|
|
|
|
2020-04-14 14:40:08 +00:00
|
|
|
void reset();
|
|
|
|
|
|
|
|
static size_t vertex_size() { return 3; }
|
|
|
|
static size_t vertex_size_bytes() { return vertex_size() * sizeof(float); }
|
2020-04-14 08:02:08 +00:00
|
|
|
};
|
|
|
|
|
2020-04-20 08:52:16 +00:00
|
|
|
// Used to identify different toolpath sub-types inside a IBuffer
|
2020-04-16 13:09:04 +00:00
|
|
|
struct Path
|
|
|
|
{
|
|
|
|
GCodeProcessor::EMoveType type{ GCodeProcessor::EMoveType::Noop };
|
|
|
|
ExtrusionRole role{ erNone };
|
|
|
|
unsigned int first{ 0 };
|
|
|
|
unsigned int last{ 0 };
|
2020-04-27 09:44:29 +00:00
|
|
|
double first_z{ 0.0f };
|
|
|
|
double last_z{ 0.0f };
|
2020-04-24 06:46:31 +00:00
|
|
|
float delta_extruder{ 0.0f };
|
2020-04-20 08:52:16 +00:00
|
|
|
float height{ 0.0f };
|
2020-04-20 11:24:25 +00:00
|
|
|
float width{ 0.0f };
|
2020-04-20 14:04:59 +00:00
|
|
|
float feedrate{ 0.0f };
|
2020-04-21 07:06:43 +00:00
|
|
|
float fan_speed{ 0.0f };
|
2020-04-21 09:38:42 +00:00
|
|
|
float volumetric_rate{ 0.0f };
|
2020-04-21 13:55:26 +00:00
|
|
|
unsigned char extruder_id{ 0 };
|
2020-04-22 14:29:07 +00:00
|
|
|
unsigned char cp_color_id{ 0 };
|
2020-04-16 13:09:04 +00:00
|
|
|
|
2020-04-20 11:24:25 +00:00
|
|
|
bool matches(const GCodeProcessor::MoveVertex& move) const {
|
2020-04-21 09:38:42 +00:00
|
|
|
return type == move.type && role == move.extrusion_role && height == move.height && width == move.width &&
|
2020-04-21 13:55:26 +00:00
|
|
|
feedrate == move.feedrate && fan_speed == move.fan_speed && volumetric_rate == move.volumetric_rate() &&
|
2020-04-22 14:29:07 +00:00
|
|
|
extruder_id == move.extruder_id && cp_color_id == move.cp_color_id;
|
2020-04-20 11:24:25 +00:00
|
|
|
}
|
2020-04-16 13:09:04 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// buffer containing indices data and shader for a specific toolpath type
|
2020-04-15 14:29:11 +00:00
|
|
|
struct IBuffer
|
|
|
|
{
|
|
|
|
unsigned int ibo_id{ 0 };
|
|
|
|
Shader shader;
|
|
|
|
std::vector<unsigned int> data;
|
|
|
|
size_t data_size{ 0 };
|
2020-04-16 13:09:04 +00:00
|
|
|
std::vector<Path> paths;
|
2020-04-15 14:29:11 +00:00
|
|
|
bool visible{ false };
|
|
|
|
|
|
|
|
void reset();
|
2020-04-16 13:09:04 +00:00
|
|
|
bool init_shader(const std::string& vertex_shader_src, const std::string& fragment_shader_src);
|
2020-04-20 11:24:25 +00:00
|
|
|
void add_path(const GCodeProcessor::MoveVertex& move);
|
2020-04-15 14:29:11 +00:00
|
|
|
};
|
|
|
|
|
2020-04-15 12:31:39 +00:00
|
|
|
struct Shells
|
|
|
|
{
|
|
|
|
GLVolumeCollection volumes;
|
|
|
|
bool visible{ false };
|
|
|
|
Shader shader;
|
|
|
|
};
|
|
|
|
|
2020-04-20 08:52:16 +00:00
|
|
|
// helper to render extrusion paths
|
2020-04-17 08:43:29 +00:00
|
|
|
struct Extrusions
|
|
|
|
{
|
2020-04-20 08:52:16 +00:00
|
|
|
struct Range
|
|
|
|
{
|
|
|
|
float min;
|
|
|
|
float max;
|
|
|
|
|
|
|
|
Range() { reset(); }
|
|
|
|
|
2020-04-21 09:38:42 +00:00
|
|
|
void update_from(const float value) { min = std::min(min, value); max = std::max(max, value); }
|
|
|
|
void reset() { min = FLT_MAX; max = -FLT_MAX; }
|
2020-04-20 08:52:16 +00:00
|
|
|
|
2020-04-22 14:29:07 +00:00
|
|
|
float step_size() const { return (max - min) / (static_cast<float>(Range_Colors.size()) - 1.0f); }
|
2020-04-21 10:51:58 +00:00
|
|
|
std::array<float, 3> get_color_at(float value) const;
|
2020-04-20 08:52:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Ranges
|
|
|
|
{
|
|
|
|
// Color mapping by layer height.
|
|
|
|
Range height;
|
2020-04-20 11:24:25 +00:00
|
|
|
// Color mapping by extrusion width.
|
|
|
|
Range width;
|
2020-04-20 14:04:59 +00:00
|
|
|
// Color mapping by feedrate.
|
|
|
|
Range feedrate;
|
2020-04-21 07:06:43 +00:00
|
|
|
// Color mapping by fan speed.
|
|
|
|
Range fan_speed;
|
2020-04-21 09:38:42 +00:00
|
|
|
// Color mapping by volumetric extrusion rate.
|
|
|
|
Range volumetric_rate;
|
2020-04-20 08:52:16 +00:00
|
|
|
|
|
|
|
void reset() {
|
|
|
|
height.reset();
|
2020-04-20 11:24:25 +00:00
|
|
|
width.reset();
|
2020-04-20 14:04:59 +00:00
|
|
|
feedrate.reset();
|
2020-04-21 07:06:43 +00:00
|
|
|
fan_speed.reset();
|
2020-04-21 09:38:42 +00:00
|
|
|
volumetric_rate.reset();
|
2020-04-20 08:52:16 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-04-17 08:43:29 +00:00
|
|
|
unsigned int role_visibility_flags{ 0 };
|
2020-04-20 08:52:16 +00:00
|
|
|
Ranges ranges;
|
2020-04-17 08:43:29 +00:00
|
|
|
|
|
|
|
void reset_role_visibility_flags() {
|
|
|
|
role_visibility_flags = 0;
|
|
|
|
for (unsigned int i = 0; i < erCount; ++i)
|
|
|
|
{
|
|
|
|
role_visibility_flags |= 1 << i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-20 08:52:16 +00:00
|
|
|
void reset_ranges() { ranges.reset(); }
|
2020-04-17 08:43:29 +00:00
|
|
|
};
|
|
|
|
|
2020-04-16 13:59:36 +00:00
|
|
|
public:
|
|
|
|
enum class EViewType : unsigned char
|
|
|
|
{
|
|
|
|
FeatureType,
|
|
|
|
Height,
|
|
|
|
Width,
|
|
|
|
Feedrate,
|
|
|
|
FanSpeed,
|
|
|
|
VolumetricRate,
|
|
|
|
Tool,
|
|
|
|
ColorPrint,
|
|
|
|
Count
|
|
|
|
};
|
|
|
|
|
|
|
|
private:
|
2020-04-21 13:55:26 +00:00
|
|
|
unsigned int m_last_result_id{ 0 };
|
2020-04-15 14:29:11 +00:00
|
|
|
VBuffer m_vertices;
|
2020-04-23 08:24:03 +00:00
|
|
|
mutable std::vector<IBuffer> m_buffers{ static_cast<size_t>(GCodeProcessor::EMoveType::Extrude) };
|
2020-04-17 11:28:25 +00:00
|
|
|
BoundingBoxf3 m_bounding_box;
|
2020-04-21 13:55:26 +00:00
|
|
|
std::vector<std::array<float, 3>> m_tool_colors;
|
2020-04-14 14:40:08 +00:00
|
|
|
std::vector<double> m_layers_zs;
|
2020-04-27 09:44:29 +00:00
|
|
|
std::array<double, 2> m_layers_z_range;
|
2020-04-18 08:41:37 +00:00
|
|
|
std::vector<ExtrusionRole> m_roles;
|
2020-04-22 14:29:07 +00:00
|
|
|
std::vector<unsigned char> m_extruder_ids;
|
2020-04-17 08:43:29 +00:00
|
|
|
Extrusions m_extrusions;
|
2020-04-15 12:31:39 +00:00
|
|
|
Shells m_shells;
|
2020-04-24 08:59:03 +00:00
|
|
|
EViewType m_view_type{ EViewType::FeatureType };
|
2020-04-18 08:41:37 +00:00
|
|
|
bool m_legend_enabled{ true };
|
2020-04-16 13:59:36 +00:00
|
|
|
|
2020-04-14 08:02:08 +00:00
|
|
|
public:
|
|
|
|
GCodeViewer() = default;
|
2020-04-14 14:40:08 +00:00
|
|
|
~GCodeViewer() { reset(); }
|
2020-04-14 08:02:08 +00:00
|
|
|
|
2020-04-16 13:09:04 +00:00
|
|
|
bool init() {
|
2020-04-17 08:43:29 +00:00
|
|
|
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Extrude, true);
|
2020-04-16 13:09:04 +00:00
|
|
|
return init_shaders();
|
|
|
|
}
|
2020-04-20 14:04:59 +00:00
|
|
|
|
2020-04-21 13:55:26 +00:00
|
|
|
// extract rendering data from the given parameters
|
2020-04-22 14:29:07 +00:00
|
|
|
void load(const GCodeProcessor::Result& gcode_result, const Print& print, bool initialized);
|
|
|
|
// recalculate ranges in dependence of what is visible and sets tool/print colors
|
|
|
|
void refresh(const GCodeProcessor::Result& gcode_result, const std::vector<std::string>& str_tool_colors);
|
2020-04-20 14:04:59 +00:00
|
|
|
|
2020-04-14 14:40:08 +00:00
|
|
|
void reset();
|
2020-04-14 08:02:08 +00:00
|
|
|
void render() const;
|
|
|
|
|
2020-04-17 11:28:25 +00:00
|
|
|
const BoundingBoxf3& get_bounding_box() const { return m_bounding_box; }
|
2020-04-14 14:40:08 +00:00
|
|
|
const std::vector<double>& get_layers_zs() const { return m_layers_zs; };
|
|
|
|
|
2020-04-16 13:59:36 +00:00
|
|
|
EViewType get_view_type() const { return m_view_type; }
|
|
|
|
void set_view_type(EViewType type) {
|
|
|
|
if (type == EViewType::Count)
|
|
|
|
type = EViewType::FeatureType;
|
|
|
|
|
|
|
|
m_view_type = type;
|
|
|
|
}
|
|
|
|
|
2020-04-23 08:24:03 +00:00
|
|
|
bool is_toolpath_move_type_visible(GCodeProcessor::EMoveType type) const;
|
2020-04-17 08:43:29 +00:00
|
|
|
void set_toolpath_move_type_visible(GCodeProcessor::EMoveType type, bool visible);
|
|
|
|
void set_toolpath_role_visibility_flags(unsigned int flags) { m_extrusions.role_visibility_flags = flags; }
|
2020-04-24 14:12:38 +00:00
|
|
|
void set_options_visibility_from_flags(unsigned int flags);
|
2020-04-27 09:44:29 +00:00
|
|
|
void set_layers_z_range(const std::array<double, 2>& layers_z_range) { m_layers_z_range = layers_z_range; }
|
2020-04-15 12:31:39 +00:00
|
|
|
|
2020-04-18 08:41:37 +00:00
|
|
|
bool is_legend_enabled() const { return m_legend_enabled; }
|
|
|
|
void enable_legend(bool enable) { m_legend_enabled = enable; }
|
|
|
|
|
2020-04-14 08:02:08 +00:00
|
|
|
private:
|
|
|
|
bool init_shaders();
|
2020-04-15 12:31:39 +00:00
|
|
|
void load_toolpaths(const GCodeProcessor::Result& gcode_result);
|
|
|
|
void load_shells(const Print& print, bool initialized);
|
|
|
|
void render_toolpaths() const;
|
|
|
|
void render_shells() const;
|
2020-04-18 08:41:37 +00:00
|
|
|
void render_overlay() const;
|
2020-04-27 10:43:51 +00:00
|
|
|
bool is_visible(ExtrusionRole role) const {
|
|
|
|
return role < erCount && (m_extrusions.role_visibility_flags & (1 << role)) != 0;
|
|
|
|
}
|
|
|
|
bool is_visible(const Path& path) const { return is_visible(path.role); }
|
|
|
|
bool is_in_z_range(const Path& path) const {
|
|
|
|
auto in_z_range = [this](double z) {
|
|
|
|
return z > m_layers_z_range[0] - EPSILON && z < m_layers_z_range[1] + EPSILON;
|
|
|
|
};
|
|
|
|
|
|
|
|
return in_z_range(path.first_z) || in_z_range(path.last_z);
|
|
|
|
}
|
2020-04-14 08:02:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace GUI
|
|
|
|
} // namespace Slic3r
|
|
|
|
|
|
|
|
#endif // ENABLE_GCODE_VIEWER
|
|
|
|
|
|
|
|
#endif // slic3r_GCodeViewer_hpp_
|
|
|
|
|