Generation of gcode paths moved to c++

This commit is contained in:
Enrico Turri 2018-06-05 10:56:55 +02:00
parent 1f79713c15
commit 5392008916
12 changed files with 1488 additions and 689 deletions

View File

@ -2248,20 +2248,14 @@ sub load_wipe_tower_toolpaths {
#============================================================================================================================== #==============================================================================================================================
} }
sub load_gcode_preview {
my ($self, $print, $gcode_preview_data, $colors) = @_;
#============================================================================================================================== #==============================================================================================================================
my $useVBOs = Slic3r::GUI::_3DScene::use_VBOs(); #sub load_gcode_preview {
$self->SetCurrent($self->GetContext) if $useVBOs; # my ($self, $print, $gcode_preview_data, $colors) = @_;
Slic3r::GUI::_3DScene::load_gcode_preview($print, $gcode_preview_data, $self->volumes, $colors, $useVBOs); #
# $self->SetCurrent($self->GetContext) if $self->UseVBOs; # $self->SetCurrent($self->GetContext) if $self->UseVBOs;
# Slic3r::GUI::_3DScene::load_gcode_preview($print, $gcode_preview_data, $self->volumes, $colors, $self->UseVBOs); # Slic3r::GUI::_3DScene::load_gcode_preview($print, $gcode_preview_data, $self->volumes, $colors, $self->UseVBOs);
#============================================================================================================================== #}
} #
#==============================================================================================================================
#sub set_toolpaths_range { #sub set_toolpaths_range {
# my ($self, $min_z, $max_z) = @_; # my ($self, $min_z, $max_z) = @_;
# $self->volumes->set_range($min_z, $max_z); # $self->volumes->set_range($min_z, $max_z);

View File

@ -134,6 +134,7 @@ sub new {
$self->{canvas3D}->set_on_enable_action_buttons($enable_action_buttons); $self->{canvas3D}->set_on_enable_action_buttons($enable_action_buttons);
#=================================================================================================================================== #===================================================================================================================================
Slic3r::GUI::_3DScene::enable_shader($self->{canvas3D}, 1); Slic3r::GUI::_3DScene::enable_shader($self->{canvas3D}, 1);
Slic3r::GUI::_3DScene::enable_force_zoom_to_bed($self->{canvas3D}, 1);
# $self->{canvas3D}->use_plain_shader(1); # $self->{canvas3D}->use_plain_shader(1);
#=================================================================================================================================== #===================================================================================================================================
$self->{canvas3D}->set_on_wipe_tower_moved(sub { $self->{canvas3D}->set_on_wipe_tower_moved(sub {

View File

@ -391,7 +391,11 @@ sub load_print {
#============================================================================================================================== #==============================================================================================================================
} else { } else {
$self->{force_sliders_full_range} = (scalar(@{$self->canvas->volumes}) == 0); $self->{force_sliders_full_range} = (scalar(@{$self->canvas->volumes}) == 0);
$self->canvas->load_gcode_preview($self->print, $self->gcode_preview_data, \@colors); #==============================================================================================================================
Slic3r::GUI::_3DScene::set_print($self->canvas, $self->print);
Slic3r::GUI::_3DScene::load_gcode_preview($self->canvas, $self->gcode_preview_data, \@colors);
# $self->canvas->load_gcode_preview($self->print, $self->gcode_preview_data, \@colors);
#==============================================================================================================================
$self->show_hide_ui_elements('full'); $self->show_hide_ui_elements('full');
# recalculates zs and update sliders accordingly # recalculates zs and update sliders accordingly

View File

@ -126,6 +126,7 @@ sub new {
$canvas->SetMinSize($canvas->GetSize); $canvas->SetMinSize($canvas->GetSize);
#============================================================================================================================== #==============================================================================================================================
Slic3r::GUI::_3DScene::set_config($canvas, $self->GetParent->{config}); Slic3r::GUI::_3DScene::set_config($canvas, $self->GetParent->{config});
Slic3r::GUI::_3DScene::enable_force_zoom_to_bed($canvas, 1);
#============================================================================================================================== #==============================================================================================================================
} }

View File

@ -183,6 +183,7 @@ sub new {
#============================================================================================================================== #==============================================================================================================================
Slic3r::GUI::_3DScene::set_config($canvas, $self->GetParent->GetParent->GetParent->{config}); Slic3r::GUI::_3DScene::set_config($canvas, $self->GetParent->GetParent->GetParent->{config});
Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($canvas); Slic3r::GUI::_3DScene::update_volumes_colors_by_extruder($canvas);
Slic3r::GUI::_3DScene::enable_force_zoom_to_bed($canvas, 1);
# $canvas->update_volumes_colors_by_extruder($self->GetParent->GetParent->GetParent->{config}); # $canvas->update_volumes_colors_by_extruder($self->GetParent->GetParent->GetParent->{config});
#============================================================================================================================== #==============================================================================================================================
} }

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,13 @@ class Model;
class ModelObject; class ModelObject;
class GCodePreviewData; class GCodePreviewData;
class DynamicPrintConfig; class DynamicPrintConfig;
//##################################################################################################################
class ExtrusionPath;
class ExtrusionMultiPath;
class ExtrusionLoop;
class ExtrusionEntity;
class ExtrusionEntityCollection;
//##################################################################################################################
// A container for interleaved arrays of 3D vertices and normals, // A container for interleaved arrays of 3D vertices and normals,
// possibly indexed by triangles and / or quads. // possibly indexed by triangles and / or quads.
@ -443,34 +450,36 @@ private:
class _3DScene class _3DScene
{ {
struct GCodePreviewVolumeIndex //##################################################################################################################
{ // struct GCodePreviewVolumeIndex
enum EType // {
{ // enum EType
Extrusion, // {
Travel, // Extrusion,
Retraction, // Travel,
Unretraction, // Retraction,
Shell, // Unretraction,
Num_Geometry_Types // Shell,
}; // Num_Geometry_Types
// };
struct FirstVolume //
{ // struct FirstVolume
EType type; // {
unsigned int flag; // EType type;
// Index of the first volume in a GLVolumeCollection. // unsigned int flag;
unsigned int id; // // Index of the first volume in a GLVolumeCollection.
// unsigned int id;
FirstVolume(EType type, unsigned int flag, unsigned int id) : type(type), flag(flag), id(id) {} //
}; // FirstVolume(EType type, unsigned int flag, unsigned int id) : type(type), flag(flag), id(id) {}
// };
std::vector<FirstVolume> first_volumes; //
// std::vector<FirstVolume> first_volumes;
void reset() { first_volumes.clear(); } //
}; // void reset() { first_volumes.clear(); }
// };
static GCodePreviewVolumeIndex s_gcode_preview_volume_index; //
// static GCodePreviewVolumeIndex s_gcode_preview_volume_index;
//##################################################################################################################
class TextureBase class TextureBase
{ {
@ -576,6 +585,7 @@ public:
static void enable_picking(wxGLCanvas* canvas, bool enable); static void enable_picking(wxGLCanvas* canvas, bool enable);
static void enable_moving(wxGLCanvas* canvas, bool enable); static void enable_moving(wxGLCanvas* canvas, bool enable);
static void enable_shader(wxGLCanvas* canvas, bool enable); static void enable_shader(wxGLCanvas* canvas, bool enable);
static void enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable);
static void allow_multisample(wxGLCanvas* canvas, bool allow); static void allow_multisample(wxGLCanvas* canvas, bool allow);
static void zoom_to_bed(wxGLCanvas* canvas); static void zoom_to_bed(wxGLCanvas* canvas);
@ -600,8 +610,15 @@ public:
// static void _glew_init(); // static void _glew_init();
//################################################################################################################## //##################################################################################################################
static void load_gcode_preview(const Print* print, const GCodePreviewData* preview_data, GLVolumeCollection* volumes, const std::vector<std::string>& str_tool_colors, bool use_VBOs); //##################################################################################################################
static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
// static void load_gcode_preview(const Print* print, const GCodePreviewData* preview_data, GLVolumeCollection* volumes, const std::vector<std::string>& str_tool_colors, bool use_VBOs);
//##################################################################################################################
//##################################################################################################################
// generates the legend texture in dependence of the current shown view type
static void generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
//##################################################################################################################
static unsigned int get_legend_texture_width(); static unsigned int get_legend_texture_width();
static unsigned int get_legend_texture_height(); static unsigned int get_legend_texture_height();
@ -634,24 +651,37 @@ public:
const std::vector<std::string> &tool_colors_str, const std::vector<std::string> &tool_colors_str,
bool use_VBOs); bool use_VBOs);
//##################################################################################################################
static void extrusionentity_to_verts(const ExtrusionPath& extrusion_path, float print_z, GLVolume& volume);
static void extrusionentity_to_verts(const ExtrusionPath& extrusion_path, float print_z, const Point& copy, GLVolume& volume);
static void extrusionentity_to_verts(const ExtrusionLoop& extrusion_loop, float print_z, const Point& copy, GLVolume& volume);
static void extrusionentity_to_verts(const ExtrusionMultiPath& extrusion_multi_path, float print_z, const Point& copy, GLVolume& volume);
static void extrusionentity_to_verts(const ExtrusionEntityCollection& extrusion_entity_collection, float print_z, const Point& copy, GLVolume& volume);
static void extrusionentity_to_verts(const ExtrusionEntity* extrusion_entity, float print_z, const Point& copy, GLVolume& volume);
static void polyline3_to_verts(const Polyline3& polyline, double width, double height, GLVolume& volume);
static void point3_to_verts(const Point3& point, double width, double height, GLVolume& volume);
//##################################################################################################################
private: private:
// generates gcode extrusion paths geometry //##################################################################################################################
static void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector<float>& tool_colors, bool use_VBOs); // // generates gcode extrusion paths geometry
// generates gcode travel paths geometry // static void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector<float>& tool_colors, bool use_VBOs);
static void _load_gcode_travel_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector<float>& tool_colors, bool use_VBOs); // // generates gcode travel paths geometry
static bool _travel_paths_by_type(const GCodePreviewData& preview_data, GLVolumeCollection& volumes); // static void _load_gcode_travel_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector<float>& tool_colors, bool use_VBOs);
static bool _travel_paths_by_feedrate(const GCodePreviewData& preview_data, GLVolumeCollection& volumes); // static bool _travel_paths_by_type(const GCodePreviewData& preview_data, GLVolumeCollection& volumes);
static bool _travel_paths_by_tool(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector<float>& tool_colors); // static bool _travel_paths_by_feedrate(const GCodePreviewData& preview_data, GLVolumeCollection& volumes);
// generates gcode retractions geometry // static bool _travel_paths_by_tool(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector<float>& tool_colors);
static void _load_gcode_retractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs); // // generates gcode retractions geometry
// generates gcode unretractions geometry // static void _load_gcode_retractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs);
static void _load_gcode_unretractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs); // // generates gcode unretractions geometry
// sets gcode geometry visibility according to user selection // static void _load_gcode_unretractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs);
static void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data, GLVolumeCollection& volumes); // // sets gcode geometry visibility according to user selection
// generates the legend texture in dependence of the current shown view type // static void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data, GLVolumeCollection& volumes);
static void _generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors); // // generates the legend texture in dependence of the current shown view type
// generates objects and wipe tower geometry // static void _generate_legend_texture(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
static void _load_shells(const Print& print, GLVolumeCollection& volumes, bool use_VBOs); // // generates objects and wipe tower geometry
// static void _load_shells(const Print& print, GLVolumeCollection& volumes, bool use_VBOs);
//##################################################################################################################
}; };
} }

View File

@ -5,6 +5,7 @@
#include "../../libslic3r/ClipperUtils.hpp" #include "../../libslic3r/ClipperUtils.hpp"
#include "../../libslic3r/PrintConfig.hpp" #include "../../libslic3r/PrintConfig.hpp"
#include "../../libslic3r/Print.hpp" #include "../../libslic3r/Print.hpp"
#include "../../libslic3r/GCode/PreviewData.hpp"
#include <GL/glew.h> #include <GL/glew.h>
@ -943,7 +944,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context)
, m_print(nullptr) , m_print(nullptr)
, m_dirty(true) , m_dirty(true)
, m_use_VBOs(false) , m_use_VBOs(false)
, m_first_render(true) , m_force_zoom_to_bed_enabled(false)
, m_apply_zoom_to_volumes_filter(false) , m_apply_zoom_to_volumes_filter(false)
, m_hover_volume_id(-1) , m_hover_volume_id(-1)
, m_warning_texture_enabled(false) , m_warning_texture_enabled(false)
@ -1190,6 +1191,12 @@ void GLCanvas3D::enable_shader(bool enable)
{ {
m_shader_enabled = enable; m_shader_enabled = enable;
} }
void GLCanvas3D::enable_force_zoom_to_bed(bool enable)
{
m_force_zoom_to_bed_enabled = enable;
}
void GLCanvas3D::allow_multisample(bool allow) void GLCanvas3D::allow_multisample(bool allow)
{ {
m_multisample_allowed = allow; m_multisample_allowed = allow;
@ -1263,14 +1270,12 @@ void GLCanvas3D::render()
if (!is_shown_on_screen()) if (!is_shown_on_screen())
return; return;
if (!set_current()) // ensures that the proper context is selected and that this canvas is initialized
if (!set_current() || !_3DScene::init(m_canvas))
return; return;
if (!_3DScene::init(m_canvas)) if (m_force_zoom_to_bed_enabled)
return; _force_zoom_to_bed();
if (m_first_render)
_before_first_render();
_camera_tranform(); _camera_tranform();
@ -1328,6 +1333,44 @@ void GLCanvas3D::set_toolpaths_range(double low, double high)
m_volumes->set_range(low, high); m_volumes->set_range(low, high);
} }
void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors)
{
if ((m_canvas != nullptr) && (m_volumes != nullptr) && (m_print != nullptr))
{
// ensures that the proper context is selected and that this canvas is initialized
if (!set_current() || !_3DScene::init(m_canvas))
return;
if (m_volumes->empty())
{
std::vector<float> tool_colors = _parse_colors(str_tool_colors);
m_gcode_preview_volume_index.reset();
_load_gcode_extrusion_paths(preview_data, tool_colors);
_load_gcode_travel_paths(preview_data, tool_colors);
_load_gcode_retractions(preview_data);
_load_gcode_unretractions(preview_data);
if (m_volumes->empty())
_3DScene::reset_legend_texture();
else
{
_3DScene::generate_legend_texture(preview_data, tool_colors);
// removes empty volumes
m_volumes->volumes.erase(std::remove_if(m_volumes->volumes.begin(), m_volumes->volumes.end(),
[](const GLVolume* volume) { return volume->print_zs.empty(); }),
m_volumes->volumes.end());
_load_shells();
}
}
_update_gcode_volumes_visibility(preview_data);
}
}
void GLCanvas3D::register_on_viewport_changed_callback(void* callback) void GLCanvas3D::register_on_viewport_changed_callback(void* callback)
{ {
if (callback != nullptr) if (callback != nullptr)
@ -1735,10 +1778,10 @@ Point GLCanvas3D::get_local_mouse_position() const
return Point(mouse_pos.x, mouse_pos.y); return Point(mouse_pos.x, mouse_pos.y);
} }
void GLCanvas3D::_before_first_render() void GLCanvas3D::_force_zoom_to_bed()
{ {
zoom_to_bed(); zoom_to_bed();
m_first_render = false; m_force_zoom_to_bed_enabled = false;
} }
void GLCanvas3D::_resize(unsigned int w, unsigned int h) void GLCanvas3D::_resize(unsigned int w, unsigned int h)
@ -2352,5 +2395,605 @@ void GLCanvas3D::_stop_timer()
m_timer->Stop(); m_timer->Stop();
} }
static inline int hex_digit_to_int(const char c)
{
return
(c >= '0' && c <= '9') ? int(c - '0') :
(c >= 'A' && c <= 'F') ? int(c - 'A') + 10 :
(c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1;
}
std::vector<float> GLCanvas3D::_parse_colors(const std::vector<std::string>& colors)
{
std::vector<float> output(colors.size() * 4, 1.0f);
for (size_t i = 0; i < colors.size(); ++i) {
const std::string& color = colors[i];
const char* c = color.data() + 1;
if ((color.size() == 7) && (color.front() == '#'))
{
for (size_t j = 0; j < 3; ++j)
{
int digit1 = hex_digit_to_int(*c++);
int digit2 = hex_digit_to_int(*c++);
if ((digit1 == -1) || (digit2 == -1))
break;
output[i * 4 + j] = float(digit1 * 16 + digit2) / 255.0f;
}
}
}
return output;
}
void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
{
// helper functions to select data in dependence of the extrusion view type
struct Helper
{
static float path_filter(GCodePreviewData::Extrusion::EViewType type, const ExtrusionPath& path)
{
switch (type)
{
case GCodePreviewData::Extrusion::FeatureType:
return (float)path.role();
case GCodePreviewData::Extrusion::Height:
return path.height;
case GCodePreviewData::Extrusion::Width:
return path.width;
case GCodePreviewData::Extrusion::Feedrate:
return path.feedrate;
case GCodePreviewData::Extrusion::VolumetricRate:
return path.feedrate * (float)path.mm3_per_mm;
case GCodePreviewData::Extrusion::Tool:
return (float)path.extruder_id;
}
return 0.0f;
}
static GCodePreviewData::Color path_color(const GCodePreviewData& data, const std::vector<float>& tool_colors, float value)
{
switch (data.extrusion.view_type)
{
case GCodePreviewData::Extrusion::FeatureType:
return data.get_extrusion_role_color((ExtrusionRole)(int)value);
case GCodePreviewData::Extrusion::Height:
return data.get_height_color(value);
case GCodePreviewData::Extrusion::Width:
return data.get_width_color(value);
case GCodePreviewData::Extrusion::Feedrate:
return data.get_feedrate_color(value);
case GCodePreviewData::Extrusion::VolumetricRate:
return data.get_volumetric_rate_color(value);
case GCodePreviewData::Extrusion::Tool:
{
GCodePreviewData::Color color;
::memcpy((void*)color.rgba, (const void*)(tool_colors.data() + (unsigned int)value * 4), 4 * sizeof(float));
return color;
}
}
return GCodePreviewData::Color::Dummy;
}
};
// Helper structure for filters
struct Filter
{
float value;
ExtrusionRole role;
GLVolume* volume;
Filter(float value, ExtrusionRole role)
: value(value)
, role(role)
, volume(nullptr)
{
}
bool operator == (const Filter& other) const
{
if (value != other.value)
return false;
if (role != other.role)
return false;
return true;
}
};
typedef std::vector<Filter> FiltersList;
size_t initial_volumes_count = m_volumes->volumes.size();
// detects filters
FiltersList filters;
for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers)
{
for (const ExtrusionPath& path : layer.paths)
{
ExtrusionRole role = path.role();
float path_filter = Helper::path_filter(preview_data.extrusion.view_type, path);
if (std::find(filters.begin(), filters.end(), Filter(path_filter, role)) == filters.end())
filters.emplace_back(path_filter, role);
}
}
// nothing to render, return
if (filters.empty())
return;
// creates a new volume for each filter
for (Filter& filter : filters)
{
m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Extrusion, (unsigned int)filter.role, (unsigned int)m_volumes->volumes.size());
GLVolume* volume = new GLVolume(Helper::path_color(preview_data, tool_colors, filter.value).rgba);
if (volume != nullptr)
{
filter.volume = volume;
m_volumes->volumes.emplace_back(volume);
}
else
{
// an error occourred - restore to previous state and return
m_gcode_preview_volume_index.first_volumes.pop_back();
if (initial_volumes_count != m_volumes->volumes.size())
{
std::vector<GLVolume*>::iterator begin = m_volumes->volumes.begin() + initial_volumes_count;
std::vector<GLVolume*>::iterator end = m_volumes->volumes.end();
for (std::vector<GLVolume*>::iterator it = begin; it < end; ++it)
{
GLVolume* volume = *it;
delete volume;
}
m_volumes->volumes.erase(begin, end);
return;
}
}
}
// populates volumes
for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers)
{
for (const ExtrusionPath& path : layer.paths)
{
float path_filter = Helper::path_filter(preview_data.extrusion.view_type, path);
FiltersList::iterator filter = std::find(filters.begin(), filters.end(), Filter(path_filter, path.role()));
if (filter != filters.end())
{
filter->volume->print_zs.push_back(layer.z);
filter->volume->offsets.push_back(filter->volume->indexed_vertex_array.quad_indices.size());
filter->volume->offsets.push_back(filter->volume->indexed_vertex_array.triangle_indices.size());
_3DScene::extrusionentity_to_verts(path, layer.z, *filter->volume);
}
}
}
// finalize volumes and sends geometry to gpu
if (m_volumes->volumes.size() > initial_volumes_count)
{
for (size_t i = initial_volumes_count; i < m_volumes->volumes.size(); ++i)
{
GLVolume* volume = m_volumes->volumes[i];
volume->bounding_box = volume->indexed_vertex_array.bounding_box();
volume->indexed_vertex_array.finalize_geometry(m_use_VBOs);
}
}
}
void GLCanvas3D::_load_gcode_travel_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
{
size_t initial_volumes_count = m_volumes->volumes.size();
m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Travel, 0, (unsigned int)initial_volumes_count);
bool res = true;
switch (preview_data.extrusion.view_type)
{
case GCodePreviewData::Extrusion::Feedrate:
{
res = _travel_paths_by_feedrate(preview_data);
break;
}
case GCodePreviewData::Extrusion::Tool:
{
res = _travel_paths_by_tool(preview_data, tool_colors);
break;
}
default:
{
res = _travel_paths_by_type(preview_data);
break;
}
}
if (!res)
{
// an error occourred - restore to previous state and return
if (initial_volumes_count != m_volumes->volumes.size())
{
std::vector<GLVolume*>::iterator begin = m_volumes->volumes.begin() + initial_volumes_count;
std::vector<GLVolume*>::iterator end = m_volumes->volumes.end();
for (std::vector<GLVolume*>::iterator it = begin; it < end; ++it)
{
GLVolume* volume = *it;
delete volume;
}
m_volumes->volumes.erase(begin, end);
}
return;
}
// finalize volumes and sends geometry to gpu
if (m_volumes->volumes.size() > initial_volumes_count)
{
for (size_t i = initial_volumes_count; i < m_volumes->volumes.size(); ++i)
{
GLVolume* volume = m_volumes->volumes[i];
volume->bounding_box = volume->indexed_vertex_array.bounding_box();
volume->indexed_vertex_array.finalize_geometry(m_use_VBOs);
}
}
}
bool GLCanvas3D::_travel_paths_by_type(const GCodePreviewData& preview_data)
{
// Helper structure for types
struct Type
{
GCodePreviewData::Travel::EType value;
GLVolume* volume;
explicit Type(GCodePreviewData::Travel::EType value)
: value(value)
, volume(nullptr)
{
}
bool operator == (const Type& other) const
{
return value == other.value;
}
};
typedef std::vector<Type> TypesList;
// colors travels by travel type
// detects types
TypesList types;
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
{
if (std::find(types.begin(), types.end(), Type(polyline.type)) == types.end())
types.emplace_back(polyline.type);
}
// nothing to render, return
if (types.empty())
return true;
// creates a new volume for each type
for (Type& type : types)
{
GLVolume* volume = new GLVolume(preview_data.travel.type_colors[type.value].rgba);
if (volume == nullptr)
return false;
else
{
type.volume = volume;
m_volumes->volumes.emplace_back(volume);
}
}
// populates volumes
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
{
TypesList::iterator type = std::find(types.begin(), types.end(), Type(polyline.type));
if (type != types.end())
{
type->volume->print_zs.push_back(unscale(polyline.polyline.bounding_box().min.z));
type->volume->offsets.push_back(type->volume->indexed_vertex_array.quad_indices.size());
type->volume->offsets.push_back(type->volume->indexed_vertex_array.triangle_indices.size());
_3DScene::polyline3_to_verts(polyline.polyline, preview_data.travel.width, preview_data.travel.height, *type->volume);
}
}
return true;
}
bool GLCanvas3D::_travel_paths_by_feedrate(const GCodePreviewData& preview_data)
{
// Helper structure for feedrate
struct Feedrate
{
float value;
GLVolume* volume;
explicit Feedrate(float value)
: value(value)
, volume(nullptr)
{
}
bool operator == (const Feedrate& other) const
{
return value == other.value;
}
};
typedef std::vector<Feedrate> FeedratesList;
// colors travels by feedrate
// detects feedrates
FeedratesList feedrates;
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
{
if (std::find(feedrates.begin(), feedrates.end(), Feedrate(polyline.feedrate)) == feedrates.end())
feedrates.emplace_back(polyline.feedrate);
}
// nothing to render, return
if (feedrates.empty())
return true;
// creates a new volume for each feedrate
for (Feedrate& feedrate : feedrates)
{
GLVolume* volume = new GLVolume(preview_data.get_feedrate_color(feedrate.value).rgba);
if (volume == nullptr)
return false;
else
{
feedrate.volume = volume;
m_volumes->volumes.emplace_back(volume);
}
}
// populates volumes
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
{
FeedratesList::iterator feedrate = std::find(feedrates.begin(), feedrates.end(), Feedrate(polyline.feedrate));
if (feedrate != feedrates.end())
{
feedrate->volume->print_zs.push_back(unscale(polyline.polyline.bounding_box().min.z));
feedrate->volume->offsets.push_back(feedrate->volume->indexed_vertex_array.quad_indices.size());
feedrate->volume->offsets.push_back(feedrate->volume->indexed_vertex_array.triangle_indices.size());
_3DScene::polyline3_to_verts(polyline.polyline, preview_data.travel.width, preview_data.travel.height, *feedrate->volume);
}
}
return true;
}
bool GLCanvas3D::_travel_paths_by_tool(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
{
// Helper structure for tool
struct Tool
{
unsigned int value;
GLVolume* volume;
explicit Tool(unsigned int value)
: value(value)
, volume(nullptr)
{
}
bool operator == (const Tool& other) const
{
return value == other.value;
}
};
typedef std::vector<Tool> ToolsList;
// colors travels by tool
// detects tools
ToolsList tools;
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
{
if (std::find(tools.begin(), tools.end(), Tool(polyline.extruder_id)) == tools.end())
tools.emplace_back(polyline.extruder_id);
}
// nothing to render, return
if (tools.empty())
return true;
// creates a new volume for each tool
for (Tool& tool : tools)
{
GLVolume* volume = new GLVolume(tool_colors.data() + tool.value * 4);
if (volume == nullptr)
return false;
else
{
tool.volume = volume;
m_volumes->volumes.emplace_back(volume);
}
}
// populates volumes
for (const GCodePreviewData::Travel::Polyline& polyline : preview_data.travel.polylines)
{
ToolsList::iterator tool = std::find(tools.begin(), tools.end(), Tool(polyline.extruder_id));
if (tool != tools.end())
{
tool->volume->print_zs.push_back(unscale(polyline.polyline.bounding_box().min.z));
tool->volume->offsets.push_back(tool->volume->indexed_vertex_array.quad_indices.size());
tool->volume->offsets.push_back(tool->volume->indexed_vertex_array.triangle_indices.size());
_3DScene::polyline3_to_verts(polyline.polyline, preview_data.travel.width, preview_data.travel.height, *tool->volume);
}
}
return true;
}
void GLCanvas3D::_load_gcode_retractions(const GCodePreviewData& preview_data)
{
m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Retraction, 0, (unsigned int)m_volumes->volumes.size());
// nothing to render, return
if (preview_data.retraction.positions.empty())
return;
GLVolume* volume = new GLVolume(preview_data.retraction.color.rgba);
if (volume != nullptr)
{
m_volumes->volumes.emplace_back(volume);
GCodePreviewData::Retraction::PositionsList copy(preview_data.retraction.positions);
std::sort(copy.begin(), copy.end(), [](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2){ return p1.position.z < p2.position.z; });
for (const GCodePreviewData::Retraction::Position& position : copy)
{
volume->print_zs.push_back(unscale(position.position.z));
volume->offsets.push_back(volume->indexed_vertex_array.quad_indices.size());
volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size());
_3DScene::point3_to_verts(position.position, position.width, position.height, *volume);
}
// finalize volumes and sends geometry to gpu
volume->bounding_box = volume->indexed_vertex_array.bounding_box();
volume->indexed_vertex_array.finalize_geometry(m_use_VBOs);
}
}
void GLCanvas3D::_load_gcode_unretractions(const GCodePreviewData& preview_data)
{
m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Unretraction, 0, (unsigned int)m_volumes->volumes.size());
// nothing to render, return
if (preview_data.unretraction.positions.empty())
return;
GLVolume* volume = new GLVolume(preview_data.unretraction.color.rgba);
if (volume != nullptr)
{
m_volumes->volumes.emplace_back(volume);
GCodePreviewData::Retraction::PositionsList copy(preview_data.unretraction.positions);
std::sort(copy.begin(), copy.end(), [](const GCodePreviewData::Retraction::Position& p1, const GCodePreviewData::Retraction::Position& p2){ return p1.position.z < p2.position.z; });
for (const GCodePreviewData::Retraction::Position& position : copy)
{
volume->print_zs.push_back(unscale(position.position.z));
volume->offsets.push_back(volume->indexed_vertex_array.quad_indices.size());
volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size());
_3DScene::point3_to_verts(position.position, position.width, position.height, *volume);
}
// finalize volumes and sends geometry to gpu
volume->bounding_box = volume->indexed_vertex_array.bounding_box();
volume->indexed_vertex_array.finalize_geometry(m_use_VBOs);
}
}
void GLCanvas3D::_load_shells()
{
size_t initial_volumes_count = m_volumes->volumes.size();
m_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Shell, 0, (unsigned int)initial_volumes_count);
if (m_print->objects.empty())
// nothing to render, return
return;
// adds objects' volumes
unsigned int object_id = 0;
for (PrintObject* obj : m_print->objects)
{
ModelObject* model_obj = obj->model_object();
std::vector<int> instance_ids(model_obj->instances.size());
for (int i = 0; i < model_obj->instances.size(); ++i)
{
instance_ids[i] = i;
}
for (ModelInstance* instance : model_obj->instances)
{
m_volumes->load_object(model_obj, object_id, instance_ids, "object", "object", "object", m_use_VBOs);
}
++object_id;
}
// adds wipe tower's volume
coordf_t max_z = m_print->objects[0]->model_object()->get_model()->bounding_box().max.z;
const PrintConfig& config = m_print->config;
unsigned int extruders_count = config.nozzle_diameter.size();
if ((extruders_count > 1) && config.single_extruder_multi_material && config.wipe_tower && !config.complete_objects) {
const float width_per_extruder = 15.f; // a simple workaround after wipe_tower_per_color_wipe got obsolete
m_volumes->load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, width_per_extruder * (extruders_count - 1), max_z, config.wipe_tower_rotation_angle, m_use_VBOs);
}
}
void GLCanvas3D::_update_gcode_volumes_visibility(const GCodePreviewData& preview_data)
{
unsigned int size = (unsigned int)m_gcode_preview_volume_index.first_volumes.size();
for (unsigned int i = 0; i < size; ++i)
{
std::vector<GLVolume*>::iterator begin = m_volumes->volumes.begin() + m_gcode_preview_volume_index.first_volumes[i].id;
std::vector<GLVolume*>::iterator end = (i + 1 < size) ? m_volumes->volumes.begin() + m_gcode_preview_volume_index.first_volumes[i + 1].id : m_volumes->volumes.end();
for (std::vector<GLVolume*>::iterator it = begin; it != end; ++it)
{
GLVolume* volume = *it;
volume->outside_printer_detection_enabled = false;
switch (m_gcode_preview_volume_index.first_volumes[i].type)
{
case GCodePreviewVolumeIndex::Extrusion:
{
if ((ExtrusionRole)m_gcode_preview_volume_index.first_volumes[i].flag == erCustom)
volume->zoom_to_volumes = false;
volume->is_active = preview_data.extrusion.is_role_flag_set((ExtrusionRole)m_gcode_preview_volume_index.first_volumes[i].flag);
break;
}
case GCodePreviewVolumeIndex::Travel:
{
volume->is_active = preview_data.travel.is_visible;
volume->zoom_to_volumes = false;
break;
}
case GCodePreviewVolumeIndex::Retraction:
{
volume->is_active = preview_data.retraction.is_visible;
volume->zoom_to_volumes = false;
break;
}
case GCodePreviewVolumeIndex::Unretraction:
{
volume->is_active = preview_data.unretraction.is_visible;
volume->zoom_to_volumes = false;
break;
}
case GCodePreviewVolumeIndex::Shell:
{
volume->is_active = preview_data.shell.is_visible;
volume->color[3] = 0.25f;
volume->zoom_to_volumes = false;
break;
}
default:
{
volume->is_active = false;
volume->zoom_to_volumes = false;
break;
}
}
}
}
}
} // namespace GUI } // namespace GUI
} // namespace Slic3r } // namespace Slic3r

View File

@ -24,6 +24,7 @@ class GLShader;
class ExPolygon; class ExPolygon;
class Print; class Print;
class PrintObject; class PrintObject;
class GCodePreviewData;
namespace GUI { namespace GUI {
@ -81,6 +82,33 @@ public:
class GLCanvas3D class GLCanvas3D
{ {
struct GCodePreviewVolumeIndex
{
enum EType
{
Extrusion,
Travel,
Retraction,
Unretraction,
Shell,
Num_Geometry_Types
};
struct FirstVolume
{
EType type;
unsigned int flag;
// Index of the first volume in a GLVolumeCollection.
unsigned int id;
FirstVolume(EType type, unsigned int flag, unsigned int id) : type(type), flag(flag), id(id) {}
};
std::vector<FirstVolume> first_volumes;
void reset() { first_volumes.clear(); }
};
public: public:
struct Camera struct Camera
{ {
@ -303,7 +331,7 @@ private:
bool m_dirty; bool m_dirty;
bool m_use_VBOs; bool m_use_VBOs;
bool m_first_render; bool m_force_zoom_to_bed_enabled;
bool m_apply_zoom_to_volumes_filter; bool m_apply_zoom_to_volumes_filter;
mutable int m_hover_volume_id; mutable int m_hover_volume_id;
bool m_warning_texture_enabled; bool m_warning_texture_enabled;
@ -313,6 +341,8 @@ private:
bool m_shader_enabled; bool m_shader_enabled;
bool m_multisample_allowed; bool m_multisample_allowed;
GCodePreviewVolumeIndex m_gcode_preview_volume_index;
PerlCallback m_on_viewport_changed_callback; PerlCallback m_on_viewport_changed_callback;
PerlCallback m_on_double_click_callback; PerlCallback m_on_double_click_callback;
PerlCallback m_on_right_click_callback; PerlCallback m_on_right_click_callback;
@ -364,6 +394,7 @@ public:
void enable_picking(bool enable); void enable_picking(bool enable);
void enable_moving(bool enable); void enable_moving(bool enable);
void enable_shader(bool enable); void enable_shader(bool enable);
void enable_force_zoom_to_bed(bool enable);
void allow_multisample(bool allow); void allow_multisample(bool allow);
void zoom_to_bed(); void zoom_to_bed();
@ -379,6 +410,8 @@ public:
std::vector<double> get_current_print_zs(bool active_only) const; std::vector<double> get_current_print_zs(bool active_only) const;
void set_toolpaths_range(double low, double high); void set_toolpaths_range(double low, double high);
void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors);
void register_on_viewport_changed_callback(void* callback); void register_on_viewport_changed_callback(void* callback);
void register_on_double_click_callback(void* callback); void register_on_double_click_callback(void* callback);
void register_on_right_click_callback(void* callback); void register_on_right_click_callback(void* callback);
@ -398,7 +431,7 @@ public:
Point get_local_mouse_position() const; Point get_local_mouse_position() const;
private: private:
void _before_first_render(); void _force_zoom_to_bed();
void _resize(unsigned int w, unsigned int h); void _resize(unsigned int w, unsigned int h);
@ -437,6 +470,24 @@ private:
void _start_timer(); void _start_timer();
void _stop_timer(); void _stop_timer();
static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
// generates gcode extrusion paths geometry
void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
// generates gcode travel paths geometry
void _load_gcode_travel_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
bool _travel_paths_by_type(const GCodePreviewData& preview_data);
bool _travel_paths_by_feedrate(const GCodePreviewData& preview_data);
bool _travel_paths_by_tool(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
// generates gcode retractions geometry
void _load_gcode_retractions(const GCodePreviewData& preview_data);
// generates gcode unretractions geometry
void _load_gcode_unretractions(const GCodePreviewData& preview_data);
// generates objects and wipe tower geometry
void _load_shells();
// sets gcode geometry visibility according to user selection
void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data);
}; };
} // namespace GUI } // namespace GUI

View File

@ -377,6 +377,13 @@ void GLCanvas3DManager::enable_shader(wxGLCanvas* canvas, bool enable)
it->second->enable_shader(enable); it->second->enable_shader(enable);
} }
void GLCanvas3DManager::enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable)
{
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->enable_force_zoom_to_bed(enable);
}
void GLCanvas3DManager::allow_multisample(wxGLCanvas* canvas, bool allow) void GLCanvas3DManager::allow_multisample(wxGLCanvas* canvas, bool allow)
{ {
CanvasesMap::iterator it = _get_canvas(canvas); CanvasesMap::iterator it = _get_canvas(canvas);
@ -443,6 +450,16 @@ void GLCanvas3DManager::set_toolpaths_range(wxGLCanvas* canvas, double low, doub
it->second->set_toolpaths_range(low, high); it->second->set_toolpaths_range(low, high);
} }
void GLCanvas3DManager::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors)
{
if (preview_data == nullptr)
return;
CanvasesMap::iterator it = _get_canvas(canvas);
if (it != m_canvases.end())
it->second->load_gcode_preview(*preview_data, str_tool_colors);
}
void GLCanvas3DManager::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback) void GLCanvas3DManager::register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback)
{ {
CanvasesMap::iterator it = _get_canvas(canvas); CanvasesMap::iterator it = _get_canvas(canvas);

View File

@ -80,6 +80,7 @@ public:
void enable_picking(wxGLCanvas* canvas, bool enable); void enable_picking(wxGLCanvas* canvas, bool enable);
void enable_moving(wxGLCanvas* canvas, bool enable); void enable_moving(wxGLCanvas* canvas, bool enable);
void enable_shader(wxGLCanvas* canvas, bool enable); void enable_shader(wxGLCanvas* canvas, bool enable);
void enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable);
void allow_multisample(wxGLCanvas* canvas, bool allow); void allow_multisample(wxGLCanvas* canvas, bool allow);
void zoom_to_bed(wxGLCanvas* canvas); void zoom_to_bed(wxGLCanvas* canvas);
@ -94,6 +95,8 @@ public:
std::vector<double> get_current_print_zs(wxGLCanvas* canvas, bool active_only) const; std::vector<double> get_current_print_zs(wxGLCanvas* canvas, bool active_only) const;
void set_toolpaths_range(wxGLCanvas* canvas, double low, double high); void set_toolpaths_range(wxGLCanvas* canvas, double low, double high);
void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback); void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback);
void register_on_double_click_callback(wxGLCanvas* canvas, void* callback); void register_on_double_click_callback(wxGLCanvas* canvas, void* callback);
void register_on_right_click_callback(wxGLCanvas* canvas, void* callback); void register_on_right_click_callback(wxGLCanvas* canvas, void* callback);

View File

@ -341,6 +341,13 @@ enable_shader(canvas, enable)
CODE: CODE:
_3DScene::enable_shader((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable); _3DScene::enable_shader((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
void
enable_force_zoom_to_bed(canvas, enable)
SV *canvas;
bool enable;
CODE:
_3DScene::enable_force_zoom_to_bed((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), enable);
void void
allow_multisample(canvas, allow) allow_multisample(canvas, allow)
SV *canvas; SV *canvas;
@ -531,13 +538,11 @@ _load_wipe_tower_toolpaths(print, volumes, tool_colors, use_VBOs)
_3DScene::_load_wipe_tower_toolpaths(print, volumes, tool_colors, use_VBOs != 0); _3DScene::_load_wipe_tower_toolpaths(print, volumes, tool_colors, use_VBOs != 0);
void void
load_gcode_preview(print, preview_data, volumes, str_tool_colors, use_VBOs) load_gcode_preview(canvas, preview_data, str_tool_colors)
Print *print; SV *canvas;
GCodePreviewData *preview_data; GCodePreviewData *preview_data;
GLVolumeCollection *volumes;
std::vector<std::string> str_tool_colors; std::vector<std::string> str_tool_colors;
int use_VBOs;
CODE: CODE:
_3DScene::load_gcode_preview(print, preview_data, volumes, str_tool_colors, use_VBOs != 0); _3DScene::load_gcode_preview((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), preview_data, str_tool_colors);
%} %}