diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index 204e19d3d..1476e8c22 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -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(); - $self->SetCurrent($self->GetContext) if $useVBOs; - Slic3r::GUI::_3DScene::load_gcode_preview($print, $gcode_preview_data, $self->volumes, $colors, $useVBOs); - +#sub load_gcode_preview { +# my ($self, $print, $gcode_preview_data, $colors) = @_; +# # $self->SetCurrent($self->GetContext) if $self->UseVBOs; # Slic3r::GUI::_3DScene::load_gcode_preview($print, $gcode_preview_data, $self->volumes, $colors, $self->UseVBOs); -#============================================================================================================================== -} - -#============================================================================================================================== +#} +# #sub set_toolpaths_range { # my ($self, $min_z, $max_z) = @_; # $self->volumes->set_range($min_z, $max_z); diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index fafd5da7c..309c2e5ed 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -134,6 +134,7 @@ sub new { $self->{canvas3D}->set_on_enable_action_buttons($enable_action_buttons); #=================================================================================================================================== 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}->set_on_wipe_tower_moved(sub { diff --git a/lib/Slic3r/GUI/Plater/3DPreview.pm b/lib/Slic3r/GUI/Plater/3DPreview.pm index 2b7f56cc1..9ea5069b4 100644 --- a/lib/Slic3r/GUI/Plater/3DPreview.pm +++ b/lib/Slic3r/GUI/Plater/3DPreview.pm @@ -391,7 +391,11 @@ sub load_print { #============================================================================================================================== } else { $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'); # recalculates zs and update sliders accordingly diff --git a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm index bb9ecd41c..84177dd0f 100644 --- a/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm +++ b/lib/Slic3r/GUI/Plater/ObjectCutDialog.pm @@ -126,6 +126,7 @@ sub new { $canvas->SetMinSize($canvas->GetSize); #============================================================================================================================== Slic3r::GUI::_3DScene::set_config($canvas, $self->GetParent->{config}); + Slic3r::GUI::_3DScene::enable_force_zoom_to_bed($canvas, 1); #============================================================================================================================== } diff --git a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm index 6fff40769..ad9c4df94 100644 --- a/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm +++ b/lib/Slic3r/GUI/Plater/ObjectPartsPanel.pm @@ -183,6 +183,7 @@ sub new { #============================================================================================================================== Slic3r::GUI::_3DScene::set_config($canvas, $self->GetParent->GetParent->GetParent->{config}); 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}); #============================================================================================================================== } diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index e55985b0e..47095e1b1 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -1377,7 +1377,10 @@ static void thick_point_to_verts(const Point3& point, } // Fill in the qverts and tverts with quads and triangles for the extrusion_path. -static inline void extrusionentity_to_verts(const ExtrusionPath &extrusion_path, float print_z, GLVolume &volume) +//################################################################################################################## +void _3DScene::extrusionentity_to_verts(const ExtrusionPath &extrusion_path, float print_z, GLVolume &volume) +//static inline void extrusionentity_to_verts(const ExtrusionPath &extrusion_path, float print_z, GLVolume &volume) +//################################################################################################################## { Lines lines = extrusion_path.polyline.lines(); std::vector widths(lines.size(), extrusion_path.width); @@ -1386,7 +1389,10 @@ static inline void extrusionentity_to_verts(const ExtrusionPath &extrusion_path, } // Fill in the qverts and tverts with quads and triangles for the extrusion_path. -static inline void extrusionentity_to_verts(const ExtrusionPath &extrusion_path, float print_z, const Point ©, GLVolume &volume) +//################################################################################################################## +void _3DScene::extrusionentity_to_verts(const ExtrusionPath &extrusion_path, float print_z, const Point ©, GLVolume &volume) +//static inline void extrusionentity_to_verts(const ExtrusionPath &extrusion_path, float print_z, const Point ©, GLVolume &volume) +//################################################################################################################## { Polyline polyline = extrusion_path.polyline; polyline.remove_duplicate_points(); @@ -1398,7 +1404,10 @@ static inline void extrusionentity_to_verts(const ExtrusionPath &extrusion_path, } // Fill in the qverts and tverts with quads and triangles for the extrusion_loop. -static inline void extrusionentity_to_verts(const ExtrusionLoop &extrusion_loop, float print_z, const Point ©, GLVolume &volume) +//################################################################################################################## +void _3DScene::extrusionentity_to_verts(const ExtrusionLoop &extrusion_loop, float print_z, const Point ©, GLVolume &volume) +//static inline void extrusionentity_to_verts(const ExtrusionLoop &extrusion_loop, float print_z, const Point ©, GLVolume &volume) +//################################################################################################################## { Lines lines; std::vector widths; @@ -1416,7 +1425,10 @@ static inline void extrusionentity_to_verts(const ExtrusionLoop &extrusion_loop, } // Fill in the qverts and tverts with quads and triangles for the extrusion_multi_path. -static inline void extrusionentity_to_verts(const ExtrusionMultiPath &extrusion_multi_path, float print_z, const Point ©, GLVolume &volume) +//################################################################################################################## +void _3DScene::extrusionentity_to_verts(const ExtrusionMultiPath &extrusion_multi_path, float print_z, const Point ©, GLVolume &volume) +//static inline void extrusionentity_to_verts(const ExtrusionMultiPath &extrusion_multi_path, float print_z, const Point ©, GLVolume &volume) +//################################################################################################################## { Lines lines; std::vector widths; @@ -1433,15 +1445,23 @@ static inline void extrusionentity_to_verts(const ExtrusionMultiPath &extrusion_ thick_lines_to_verts(lines, widths, heights, false, print_z, volume); } -static void extrusionentity_to_verts(const ExtrusionEntity *extrusion_entity, float print_z, const Point ©, GLVolume &volume); +//################################################################################################################## +//static void extrusionentity_to_verts(const ExtrusionEntity *extrusion_entity, float print_z, const Point ©, GLVolume &volume); +//################################################################################################################## -static inline void extrusionentity_to_verts(const ExtrusionEntityCollection &extrusion_entity_collection, float print_z, const Point ©, GLVolume &volume) +//################################################################################################################## +void _3DScene::extrusionentity_to_verts(const ExtrusionEntityCollection &extrusion_entity_collection, float print_z, const Point ©, GLVolume &volume) +//static inline void extrusionentity_to_verts(const ExtrusionEntityCollection &extrusion_entity_collection, float print_z, const Point ©, GLVolume &volume) +//################################################################################################################## { for (const ExtrusionEntity *extrusion_entity : extrusion_entity_collection.entities) extrusionentity_to_verts(extrusion_entity, print_z, copy, volume); } -static void extrusionentity_to_verts(const ExtrusionEntity *extrusion_entity, float print_z, const Point ©, GLVolume &volume) +//################################################################################################################## +void _3DScene::extrusionentity_to_verts(const ExtrusionEntity *extrusion_entity, float print_z, const Point ©, GLVolume &volume) +//static void extrusionentity_to_verts(const ExtrusionEntity *extrusion_entity, float print_z, const Point ©, GLVolume &volume) +//################################################################################################################## { if (extrusion_entity != nullptr) { auto *extrusion_path = dynamic_cast(extrusion_entity); @@ -1468,7 +1488,10 @@ static void extrusionentity_to_verts(const ExtrusionEntity *extrusion_entity, fl } } -static void polyline3_to_verts(const Polyline3& polyline, double width, double height, GLVolume& volume) +//################################################################################################################## +void _3DScene::polyline3_to_verts(const Polyline3& polyline, double width, double height, GLVolume& volume) +//static void polyline3_to_verts(const Polyline3& polyline, double width, double height, GLVolume& volume) +//################################################################################################################## { Lines3 lines = polyline.lines(); std::vector widths(lines.size(), width); @@ -1476,12 +1499,17 @@ static void polyline3_to_verts(const Polyline3& polyline, double width, double h thick_lines_to_verts(lines, widths, heights, false, volume); } -static void point3_to_verts(const Point3& point, double width, double height, GLVolume& volume) +//################################################################################################################## +void _3DScene::point3_to_verts(const Point3& point, double width, double height, GLVolume& volume) +//static void point3_to_verts(const Point3& point, double width, double height, GLVolume& volume) +//################################################################################################################## { thick_point_to_verts(point, width, height, volume); } -_3DScene::GCodePreviewVolumeIndex _3DScene::s_gcode_preview_volume_index; +//################################################################################################################## +//_3DScene::GCodePreviewVolumeIndex _3DScene::s_gcode_preview_volume_index; +//################################################################################################################## _3DScene::LegendTexture _3DScene::s_legend_texture; _3DScene::WarningTexture _3DScene::s_warning_texture; //################################################################################################################## @@ -1868,6 +1896,11 @@ void _3DScene::enable_shader(wxGLCanvas* canvas, bool enable) s_canvas_mgr.enable_shader(canvas, enable); } +void _3DScene::enable_force_zoom_to_bed(wxGLCanvas* canvas, bool enable) +{ + s_canvas_mgr.enable_force_zoom_to_bed(canvas, enable); +} + void _3DScene::allow_multisample(wxGLCanvas* canvas, bool allow) { s_canvas_mgr.allow_multisample(canvas, allow); @@ -1976,40 +2009,54 @@ static inline std::vector parse_colors(const std::vector &sc return output; } -void _3DScene::load_gcode_preview(const Print* print, const GCodePreviewData* preview_data, GLVolumeCollection* volumes, const std::vector& str_tool_colors, bool use_VBOs) +//################################################################################################################## +void _3DScene::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector& str_tool_colors) { - if ((preview_data == nullptr) || (volumes == nullptr)) - return; - - if (volumes->empty()) - { - std::vector tool_colors = parse_colors(str_tool_colors); - - s_gcode_preview_volume_index.reset(); - - _load_gcode_extrusion_paths(*preview_data, *volumes, tool_colors, use_VBOs); - _load_gcode_travel_paths(*preview_data, *volumes, tool_colors, use_VBOs); - _load_gcode_retractions(*preview_data, *volumes, use_VBOs); - _load_gcode_unretractions(*preview_data, *volumes, use_VBOs); - - if (volumes->empty()) - reset_legend_texture(); - else - { - _generate_legend_texture(*preview_data, tool_colors); - - // removes empty volumes - volumes->volumes.erase(std::remove_if(volumes->volumes.begin(), volumes->volumes.end(), - [](const GLVolume *volume) { return volume->print_zs.empty(); }), - volumes->volumes.end()); - - _load_shells(*print, *volumes, use_VBOs); - } - } - - _update_gcode_volumes_visibility(*preview_data, *volumes); + s_canvas_mgr.load_gcode_preview(canvas, preview_data, str_tool_colors); } +//void _3DScene::load_gcode_preview(const Print* print, const GCodePreviewData* preview_data, GLVolumeCollection* volumes, const std::vector& str_tool_colors, bool use_VBOs) +//{ +// if ((preview_data == nullptr) || (volumes == nullptr)) +// return; +// +// if (volumes->empty()) +// { +// std::vector tool_colors = parse_colors(str_tool_colors); +// +// s_gcode_preview_volume_index.reset(); +// +// _load_gcode_extrusion_paths(*preview_data, *volumes, tool_colors, use_VBOs); +// _load_gcode_travel_paths(*preview_data, *volumes, tool_colors, use_VBOs); +// _load_gcode_retractions(*preview_data, *volumes, use_VBOs); +// _load_gcode_unretractions(*preview_data, *volumes, use_VBOs); +// +// if (volumes->empty()) +// reset_legend_texture(); +// else +// { +// _generate_legend_texture(*preview_data, tool_colors); +// +// // removes empty volumes +// volumes->volumes.erase(std::remove_if(volumes->volumes.begin(), volumes->volumes.end(), +// [](const GLVolume *volume) { return volume->print_zs.empty(); }), +// volumes->volumes.end()); +// +// _load_shells(*print, *volumes, use_VBOs); +// } +// } +// +// _update_gcode_volumes_visibility(*preview_data, *volumes); +//} +//################################################################################################################## + +//################################################################################################################## +void _3DScene::generate_legend_texture(const GCodePreviewData& preview_data, const std::vector& tool_colors) +{ + s_legend_texture.generate(preview_data, tool_colors); +} +//################################################################################################################## + unsigned int _3DScene::get_legend_texture_width() { return s_legend_texture.get_texture_width(); @@ -2414,579 +2461,581 @@ void _3DScene::_load_wipe_tower_toolpaths( BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end"; } -void _3DScene::_load_gcode_extrusion_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector& tool_colors, bool use_VBOs) -{ - // 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& 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 FiltersList; - size_t initial_volumes_count = 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) - { - s_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Extrusion, (unsigned int)filter.role, (unsigned int)volumes.volumes.size()); - GLVolume* volume = new GLVolume(Helper::path_color(preview_data, tool_colors, filter.value).rgba); - if (volume != nullptr) - { - filter.volume = volume; - volumes.volumes.emplace_back(volume); - } - else - { - // an error occourred - restore to previous state and return - s_gcode_preview_volume_index.first_volumes.pop_back(); - if (initial_volumes_count != volumes.volumes.size()) - { - std::vector::iterator begin = volumes.volumes.begin() + initial_volumes_count; - std::vector::iterator end = volumes.volumes.end(); - for (std::vector::iterator it = begin; it < end; ++it) - { - GLVolume* volume = *it; - delete volume; - } - 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()); - - extrusionentity_to_verts(path, layer.z, *filter->volume); - } - } - } - - // finalize volumes and sends geometry to gpu - if (volumes.volumes.size() > initial_volumes_count) - { - for (size_t i = initial_volumes_count; i < volumes.volumes.size(); ++i) - { - GLVolume* volume = volumes.volumes[i]; - volume->bounding_box = volume->indexed_vertex_array.bounding_box(); - volume->indexed_vertex_array.finalize_geometry(use_VBOs); - } - } -} - -void _3DScene::_load_gcode_travel_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector& tool_colors, bool use_VBOs) -{ - size_t initial_volumes_count = volumes.volumes.size(); - s_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, volumes); - break; - } - case GCodePreviewData::Extrusion::Tool: - { - res = _travel_paths_by_tool(preview_data, volumes, tool_colors); - break; - } - default: - { - res = _travel_paths_by_type(preview_data, volumes); - break; - } - } - - if (!res) - { - // an error occourred - restore to previous state and return - if (initial_volumes_count != volumes.volumes.size()) - { - std::vector::iterator begin = volumes.volumes.begin() + initial_volumes_count; - std::vector::iterator end = volumes.volumes.end(); - for (std::vector::iterator it = begin; it < end; ++it) - { - GLVolume* volume = *it; - delete volume; - } - volumes.volumes.erase(begin, end); - } - - return; - } - - // finalize volumes and sends geometry to gpu - if (volumes.volumes.size() > initial_volumes_count) - { - for (size_t i = initial_volumes_count; i < volumes.volumes.size(); ++i) - { - GLVolume* volume = volumes.volumes[i]; - volume->bounding_box = volume->indexed_vertex_array.bounding_box(); - volume->indexed_vertex_array.finalize_geometry(use_VBOs); - } - } -} - -bool _3DScene::_travel_paths_by_type(const GCodePreviewData& preview_data, GLVolumeCollection& volumes) -{ - // 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 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; - 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()); - - polyline3_to_verts(polyline.polyline, preview_data.travel.width, preview_data.travel.height, *type->volume); - } - } - - return true; -} - -bool _3DScene::_travel_paths_by_feedrate(const GCodePreviewData& preview_data, GLVolumeCollection& volumes) -{ - // 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 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; - 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()); - - polyline3_to_verts(polyline.polyline, preview_data.travel.width, preview_data.travel.height, *feedrate->volume); - } - } - - return true; -} - -bool _3DScene::_travel_paths_by_tool(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector& 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 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; - 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()); - - polyline3_to_verts(polyline.polyline, preview_data.travel.width, preview_data.travel.height, *tool->volume); - } - } - - return true; -} - -void _3DScene::_load_gcode_retractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs) -{ - s_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Retraction, 0, (unsigned int)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) - { - 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()); - - 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(use_VBOs); - } -} - -void _3DScene::_load_gcode_unretractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs) -{ - s_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Unretraction, 0, (unsigned int)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) - { - 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()); - - 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(use_VBOs); - } -} - -void _3DScene::_update_gcode_volumes_visibility(const GCodePreviewData& preview_data, GLVolumeCollection& volumes) -{ - unsigned int size = (unsigned int)s_gcode_preview_volume_index.first_volumes.size(); - for (unsigned int i = 0; i < size; ++i) - { - std::vector::iterator begin = volumes.volumes.begin() + s_gcode_preview_volume_index.first_volumes[i].id; - std::vector::iterator end = (i + 1 < size) ? volumes.volumes.begin() + s_gcode_preview_volume_index.first_volumes[i + 1].id : volumes.volumes.end(); - - for (std::vector::iterator it = begin; it != end; ++it) - { - GLVolume* volume = *it; - volume->outside_printer_detection_enabled = false; - - switch (s_gcode_preview_volume_index.first_volumes[i].type) - { - case GCodePreviewVolumeIndex::Extrusion: - { - if ((ExtrusionRole)s_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)s_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; - } - } - } - } -} - -void _3DScene::_generate_legend_texture(const GCodePreviewData& preview_data, const std::vector& tool_colors) -{ - s_legend_texture.generate(preview_data, tool_colors); -} - -void _3DScene::_load_shells(const Print& print, GLVolumeCollection& volumes, bool use_VBOs) -{ - size_t initial_volumes_count = volumes.volumes.size(); - s_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Shell, 0, (unsigned int)initial_volumes_count); - - if (print.objects.empty()) - // nothing to render, return - return; - - // adds objects' volumes - unsigned int object_id = 0; - for (PrintObject* obj : print.objects) - { - ModelObject* model_obj = obj->model_object(); - - std::vector 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) - { - volumes.load_object(model_obj, object_id, instance_ids, "object", "object", "object", use_VBOs); - } - - ++object_id; - } - - // adds wipe tower's volume - coordf_t max_z = print.objects[0]->model_object()->get_model()->bounding_box().max.z; - const PrintConfig& config = 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 - 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, use_VBOs); - } -} +//################################################################################################################## +//void _3DScene::_load_gcode_extrusion_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector& tool_colors, bool use_VBOs) +//{ +// // 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& 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 FiltersList; +// size_t initial_volumes_count = 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) +// { +// s_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Extrusion, (unsigned int)filter.role, (unsigned int)volumes.volumes.size()); +// GLVolume* volume = new GLVolume(Helper::path_color(preview_data, tool_colors, filter.value).rgba); +// if (volume != nullptr) +// { +// filter.volume = volume; +// volumes.volumes.emplace_back(volume); +// } +// else +// { +// // an error occourred - restore to previous state and return +// s_gcode_preview_volume_index.first_volumes.pop_back(); +// if (initial_volumes_count != volumes.volumes.size()) +// { +// std::vector::iterator begin = volumes.volumes.begin() + initial_volumes_count; +// std::vector::iterator end = volumes.volumes.end(); +// for (std::vector::iterator it = begin; it < end; ++it) +// { +// GLVolume* volume = *it; +// delete volume; +// } +// 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()); +// +// extrusionentity_to_verts(path, layer.z, *filter->volume); +// } +// } +// } +// +// // finalize volumes and sends geometry to gpu +// if (volumes.volumes.size() > initial_volumes_count) +// { +// for (size_t i = initial_volumes_count; i < volumes.volumes.size(); ++i) +// { +// GLVolume* volume = volumes.volumes[i]; +// volume->bounding_box = volume->indexed_vertex_array.bounding_box(); +// volume->indexed_vertex_array.finalize_geometry(use_VBOs); +// } +// } +//} +// +//void _3DScene::_load_gcode_travel_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector& tool_colors, bool use_VBOs) +//{ +// size_t initial_volumes_count = volumes.volumes.size(); +// s_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, volumes); +// break; +// } +// case GCodePreviewData::Extrusion::Tool: +// { +// res = _travel_paths_by_tool(preview_data, volumes, tool_colors); +// break; +// } +// default: +// { +// res = _travel_paths_by_type(preview_data, volumes); +// break; +// } +// } +// +// if (!res) +// { +// // an error occourred - restore to previous state and return +// if (initial_volumes_count != volumes.volumes.size()) +// { +// std::vector::iterator begin = volumes.volumes.begin() + initial_volumes_count; +// std::vector::iterator end = volumes.volumes.end(); +// for (std::vector::iterator it = begin; it < end; ++it) +// { +// GLVolume* volume = *it; +// delete volume; +// } +// volumes.volumes.erase(begin, end); +// } +// +// return; +// } +// +// // finalize volumes and sends geometry to gpu +// if (volumes.volumes.size() > initial_volumes_count) +// { +// for (size_t i = initial_volumes_count; i < volumes.volumes.size(); ++i) +// { +// GLVolume* volume = volumes.volumes[i]; +// volume->bounding_box = volume->indexed_vertex_array.bounding_box(); +// volume->indexed_vertex_array.finalize_geometry(use_VBOs); +// } +// } +//} +// +//bool _3DScene::_travel_paths_by_type(const GCodePreviewData& preview_data, GLVolumeCollection& volumes) +//{ +// // 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 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; +// 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()); +// +// polyline3_to_verts(polyline.polyline, preview_data.travel.width, preview_data.travel.height, *type->volume); +// } +// } +// +// return true; +//} +// +//bool _3DScene::_travel_paths_by_feedrate(const GCodePreviewData& preview_data, GLVolumeCollection& volumes) +//{ +// // 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 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; +// 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()); +// +// polyline3_to_verts(polyline.polyline, preview_data.travel.width, preview_data.travel.height, *feedrate->volume); +// } +// } +// +// return true; +//} +// +//bool _3DScene::_travel_paths_by_tool(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector& 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 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; +// 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()); +// +// polyline3_to_verts(polyline.polyline, preview_data.travel.width, preview_data.travel.height, *tool->volume); +// } +// } +// +// return true; +//} +// +//void _3DScene::_load_gcode_retractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs) +//{ +// s_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Retraction, 0, (unsigned int)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) +// { +// 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()); +// +// 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(use_VBOs); +// } +//} +// +//void _3DScene::_load_gcode_unretractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs) +//{ +// s_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Unretraction, 0, (unsigned int)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) +// { +// 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()); +// +// 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(use_VBOs); +// } +//} +// +//void _3DScene::_update_gcode_volumes_visibility(const GCodePreviewData& preview_data, GLVolumeCollection& volumes) +//{ +// unsigned int size = (unsigned int)s_gcode_preview_volume_index.first_volumes.size(); +// for (unsigned int i = 0; i < size; ++i) +// { +// std::vector::iterator begin = volumes.volumes.begin() + s_gcode_preview_volume_index.first_volumes[i].id; +// std::vector::iterator end = (i + 1 < size) ? volumes.volumes.begin() + s_gcode_preview_volume_index.first_volumes[i + 1].id : volumes.volumes.end(); +// +// for (std::vector::iterator it = begin; it != end; ++it) +// { +// GLVolume* volume = *it; +// volume->outside_printer_detection_enabled = false; +// +// switch (s_gcode_preview_volume_index.first_volumes[i].type) +// { +// case GCodePreviewVolumeIndex::Extrusion: +// { +// if ((ExtrusionRole)s_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)s_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; +// } +// } +// } +// } +//} +// +//void _3DScene::_generate_legend_texture(const GCodePreviewData& preview_data, const std::vector& tool_colors) +//{ +// s_legend_texture.generate(preview_data, tool_colors); +//} +// +//void _3DScene::_load_shells(const Print& print, GLVolumeCollection& volumes, bool use_VBOs) +//{ +// size_t initial_volumes_count = volumes.volumes.size(); +// s_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Shell, 0, (unsigned int)initial_volumes_count); +// +// if (print.objects.empty()) +// // nothing to render, return +// return; +// +// // adds objects' volumes +// unsigned int object_id = 0; +// for (PrintObject* obj : print.objects) +// { +// ModelObject* model_obj = obj->model_object(); +// +// std::vector 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) +// { +// volumes.load_object(model_obj, object_id, instance_ids, "object", "object", "object", use_VBOs); +// } +// +// ++object_id; +// } +// +// // adds wipe tower's volume +// coordf_t max_z = print.objects[0]->model_object()->get_model()->bounding_box().max.z; +// const PrintConfig& config = 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 +// 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, use_VBOs); +// } +//} +//################################################################################################################## } // namespace Slic3r diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index aff40f4d7..69530b84f 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -23,6 +23,13 @@ class Model; class ModelObject; class GCodePreviewData; class DynamicPrintConfig; +//################################################################################################################## +class ExtrusionPath; +class ExtrusionMultiPath; +class ExtrusionLoop; +class ExtrusionEntity; +class ExtrusionEntityCollection; +//################################################################################################################## // A container for interleaved arrays of 3D vertices and normals, // possibly indexed by triangles and / or quads. @@ -443,34 +450,36 @@ private: class _3DScene { - 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 first_volumes; - - void reset() { first_volumes.clear(); } - }; - - static GCodePreviewVolumeIndex s_gcode_preview_volume_index; +//################################################################################################################## +// 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 first_volumes; +// +// void reset() { first_volumes.clear(); } +// }; +// +// static GCodePreviewVolumeIndex s_gcode_preview_volume_index; +//################################################################################################################## class TextureBase { @@ -576,6 +585,7 @@ public: static void enable_picking(wxGLCanvas* canvas, bool enable); static void enable_moving(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 zoom_to_bed(wxGLCanvas* canvas); @@ -600,8 +610,15 @@ public: // static void _glew_init(); //################################################################################################################## - static void load_gcode_preview(const Print* print, const GCodePreviewData* preview_data, GLVolumeCollection* volumes, const std::vector& str_tool_colors, bool use_VBOs); +//################################################################################################################## + static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector& str_tool_colors); +// static void load_gcode_preview(const Print* print, const GCodePreviewData* preview_data, GLVolumeCollection* volumes, const std::vector& 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& tool_colors); +//################################################################################################################## static unsigned int get_legend_texture_width(); static unsigned int get_legend_texture_height(); @@ -634,24 +651,37 @@ public: const std::vector &tool_colors_str, 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: - // generates gcode extrusion paths geometry - static void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector& tool_colors, bool use_VBOs); - // generates gcode travel paths geometry - static void _load_gcode_travel_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector& tool_colors, bool use_VBOs); - static bool _travel_paths_by_type(const GCodePreviewData& preview_data, GLVolumeCollection& volumes); - static bool _travel_paths_by_feedrate(const GCodePreviewData& preview_data, GLVolumeCollection& volumes); - static bool _travel_paths_by_tool(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector& tool_colors); - // generates gcode retractions geometry - static void _load_gcode_retractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs); - // generates gcode unretractions geometry - static void _load_gcode_unretractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs); - // sets gcode geometry visibility according to user selection - static void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data, GLVolumeCollection& volumes); - // generates the legend texture in dependence of the current shown view type - static void _generate_legend_texture(const GCodePreviewData& preview_data, const std::vector& tool_colors); - // generates objects and wipe tower geometry - static void _load_shells(const Print& print, GLVolumeCollection& volumes, bool use_VBOs); +//################################################################################################################## +// // generates gcode extrusion paths geometry +// static void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector& tool_colors, bool use_VBOs); +// // generates gcode travel paths geometry +// static void _load_gcode_travel_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector& tool_colors, bool use_VBOs); +// static bool _travel_paths_by_type(const GCodePreviewData& preview_data, GLVolumeCollection& volumes); +// static bool _travel_paths_by_feedrate(const GCodePreviewData& preview_data, GLVolumeCollection& volumes); +// static bool _travel_paths_by_tool(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector& tool_colors); +// // generates gcode retractions geometry +// static void _load_gcode_retractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs); +// // generates gcode unretractions geometry +// static void _load_gcode_unretractions(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, bool use_VBOs); +// // sets gcode geometry visibility according to user selection +// static void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data, GLVolumeCollection& volumes); +// // generates the legend texture in dependence of the current shown view type +// static void _generate_legend_texture(const GCodePreviewData& preview_data, const std::vector& tool_colors); +// // generates objects and wipe tower geometry +// static void _load_shells(const Print& print, GLVolumeCollection& volumes, bool use_VBOs); +//################################################################################################################## }; } diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index d48cc0ccc..7251e600b 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -5,6 +5,7 @@ #include "../../libslic3r/ClipperUtils.hpp" #include "../../libslic3r/PrintConfig.hpp" #include "../../libslic3r/Print.hpp" +#include "../../libslic3r/GCode/PreviewData.hpp" #include @@ -943,7 +944,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas, wxGLContext* context) , m_print(nullptr) , m_dirty(true) , m_use_VBOs(false) - , m_first_render(true) + , m_force_zoom_to_bed_enabled(false) , m_apply_zoom_to_volumes_filter(false) , m_hover_volume_id(-1) , m_warning_texture_enabled(false) @@ -1190,6 +1191,12 @@ void GLCanvas3D::enable_shader(bool 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) { m_multisample_allowed = allow; @@ -1263,14 +1270,12 @@ void GLCanvas3D::render() if (!is_shown_on_screen()) 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; - if (!_3DScene::init(m_canvas)) - return; - - if (m_first_render) - _before_first_render(); + if (m_force_zoom_to_bed_enabled) + _force_zoom_to_bed(); _camera_tranform(); @@ -1328,6 +1333,44 @@ void GLCanvas3D::set_toolpaths_range(double low, double high) m_volumes->set_range(low, high); } +void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const std::vector& 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 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) { if (callback != nullptr) @@ -1735,10 +1778,10 @@ Point GLCanvas3D::get_local_mouse_position() const return Point(mouse_pos.x, mouse_pos.y); } -void GLCanvas3D::_before_first_render() +void GLCanvas3D::_force_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) @@ -2352,5 +2395,605 @@ void GLCanvas3D::_stop_timer() 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 GLCanvas3D::_parse_colors(const std::vector& colors) +{ + std::vector 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& 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& 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 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::iterator begin = m_volumes->volumes.begin() + initial_volumes_count; + std::vector::iterator end = m_volumes->volumes.end(); + for (std::vector::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& 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::iterator begin = m_volumes->volumes.begin() + initial_volumes_count; + std::vector::iterator end = m_volumes->volumes.end(); + for (std::vector::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 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 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& 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 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 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::iterator begin = m_volumes->volumes.begin() + m_gcode_preview_volume_index.first_volumes[i].id; + std::vector::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::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 Slic3r diff --git a/xs/src/slic3r/GUI/GLCanvas3D.hpp b/xs/src/slic3r/GUI/GLCanvas3D.hpp index d2c9f259c..b7ba7ef6b 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.hpp @@ -24,6 +24,7 @@ class GLShader; class ExPolygon; class Print; class PrintObject; +class GCodePreviewData; namespace GUI { @@ -81,6 +82,33 @@ public: 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 first_volumes; + + void reset() { first_volumes.clear(); } + }; + public: struct Camera { @@ -303,7 +331,7 @@ private: bool m_dirty; bool m_use_VBOs; - bool m_first_render; + bool m_force_zoom_to_bed_enabled; bool m_apply_zoom_to_volumes_filter; mutable int m_hover_volume_id; bool m_warning_texture_enabled; @@ -313,6 +341,8 @@ private: bool m_shader_enabled; bool m_multisample_allowed; + GCodePreviewVolumeIndex m_gcode_preview_volume_index; + PerlCallback m_on_viewport_changed_callback; PerlCallback m_on_double_click_callback; PerlCallback m_on_right_click_callback; @@ -364,6 +394,7 @@ public: void enable_picking(bool enable); void enable_moving(bool enable); void enable_shader(bool enable); + void enable_force_zoom_to_bed(bool enable); void allow_multisample(bool allow); void zoom_to_bed(); @@ -379,6 +410,8 @@ public: std::vector get_current_print_zs(bool active_only) const; void set_toolpaths_range(double low, double high); + void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector& str_tool_colors); + void register_on_viewport_changed_callback(void* callback); void register_on_double_click_callback(void* callback); void register_on_right_click_callback(void* callback); @@ -398,7 +431,7 @@ public: Point get_local_mouse_position() const; private: - void _before_first_render(); + void _force_zoom_to_bed(); void _resize(unsigned int w, unsigned int h); @@ -437,6 +470,24 @@ private: void _start_timer(); void _stop_timer(); + + static std::vector _parse_colors(const std::vector& colors); + + // generates gcode extrusion paths geometry + void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector& tool_colors); + // generates gcode travel paths geometry + void _load_gcode_travel_paths(const GCodePreviewData& preview_data, const std::vector& 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& 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 diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp index cbd9c15cb..850ccc697 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.cpp @@ -377,6 +377,13 @@ void GLCanvas3DManager::enable_shader(wxGLCanvas* canvas, bool 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) { 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); } +void GLCanvas3DManager::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector& 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) { CanvasesMap::iterator it = _get_canvas(canvas); diff --git a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp index e28a0aba9..5a874de12 100644 --- a/xs/src/slic3r/GUI/GLCanvas3DManager.hpp +++ b/xs/src/slic3r/GUI/GLCanvas3DManager.hpp @@ -80,6 +80,7 @@ public: void enable_picking(wxGLCanvas* canvas, bool enable); void enable_moving(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 zoom_to_bed(wxGLCanvas* canvas); @@ -94,6 +95,8 @@ public: std::vector get_current_print_zs(wxGLCanvas* canvas, bool active_only) const; void set_toolpaths_range(wxGLCanvas* canvas, double low, double high); + void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector& str_tool_colors); + void register_on_viewport_changed_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); diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp index fac52a02e..8b454d3c3 100644 --- a/xs/xsp/GUI_3DScene.xsp +++ b/xs/xsp/GUI_3DScene.xsp @@ -341,6 +341,13 @@ enable_shader(canvas, enable) CODE: _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 allow_multisample(canvas, allow) 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); void -load_gcode_preview(print, preview_data, volumes, str_tool_colors, use_VBOs) - Print *print; +load_gcode_preview(canvas, preview_data, str_tool_colors) + SV *canvas; GCodePreviewData *preview_data; - GLVolumeCollection *volumes; std::vector str_tool_colors; - int use_VBOs; 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); %}