diff --git a/lib/Slic3r/GUI/Plater/3DPreview.pm b/lib/Slic3r/GUI/Plater/3DPreview.pm index 1f7408b7a..fb1a9bbfc 100644 --- a/lib/Slic3r/GUI/Plater/3DPreview.pm +++ b/lib/Slic3r/GUI/Plater/3DPreview.pm @@ -80,6 +80,7 @@ sub new { my $checkbox_travel = Wx::CheckBox->new($self, -1, "Travel"); my $checkbox_retractions = Wx::CheckBox->new($self, -1, "Retractions"); my $checkbox_unretractions = Wx::CheckBox->new($self, -1, "Unretractions"); + my $checkbox_shells = Wx::CheckBox->new($self, -1, "Shells"); my $hsizer = Wx::BoxSizer->new(wxHORIZONTAL); my $vsizer = Wx::BoxSizer->new(wxVERTICAL); @@ -106,6 +107,8 @@ sub new { $bottom_sizer->Add($checkbox_retractions, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); $bottom_sizer->AddSpacer(10); $bottom_sizer->Add($checkbox_unretractions, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); + $bottom_sizer->AddSpacer(10); + $bottom_sizer->Add($checkbox_shells, 0, wxEXPAND | wxALL | wxALIGN_CENTER_VERTICAL, 5); my $sizer = Wx::BoxSizer->new(wxHORIZONTAL); $sizer->Add($canvas, 1, wxALL | wxEXPAND, 0); @@ -217,6 +220,12 @@ sub new { $self->refresh_print; $self->auto_zoom(1); }); + EVT_CHECKBOX($self, $checkbox_shells, sub { + $self->print->set_gcode_preview_shells_visible($checkbox_shells->IsChecked()); + $self->auto_zoom(0); + $self->refresh_print; + $self->auto_zoom(1); + }); $self->SetSizer($main_sizer); $self->SetMinSize($self->GetSize); diff --git a/xs/src/libslic3r/GCode/Analyzer.cpp b/xs/src/libslic3r/GCode/Analyzer.cpp index 0288770b0..c64857566 100644 --- a/xs/src/libslic3r/GCode/Analyzer.cpp +++ b/xs/src/libslic3r/GCode/Analyzer.cpp @@ -298,7 +298,12 @@ void GCodeAnalyzer::PreviewData::Retraction::set_default() { color = Default_Color; is_visible = false; -}; +} + +void GCodeAnalyzer::PreviewData::Shell::set_default() +{ + is_visible = false; +} GCodeAnalyzer::PreviewData::PreviewData() { @@ -311,6 +316,7 @@ void GCodeAnalyzer::PreviewData::set_default() travel.set_default(); retraction.set_default(); unretraction.set_default(); + shell.set_default(); } void GCodeAnalyzer::PreviewData::reset() diff --git a/xs/src/libslic3r/GCode/Analyzer.hpp b/xs/src/libslic3r/GCode/Analyzer.hpp index 34f1537af..6d0213422 100644 --- a/xs/src/libslic3r/GCode/Analyzer.hpp +++ b/xs/src/libslic3r/GCode/Analyzer.hpp @@ -256,10 +256,18 @@ public: void set_default(); }; + struct Shell + { + bool is_visible; + + void set_default(); + }; + Extrusion extrusion; Travel travel; Retraction retraction; Retraction unretraction; + Shell shell; PreviewData(); diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index d0af38327..172b26cc4 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -102,6 +102,11 @@ void Print::set_gcode_preview_unretractions_visible(bool visible) gcode_preview.unretraction.is_visible = visible; } +void Print::set_gcode_preview_shells_visible(bool visible) +{ + gcode_preview.shell.is_visible = visible; +} + PrintRegion* Print::add_region() { regions.push_back(new PrintRegion(this)); diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index 4c2284446..0a6c143b9 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -262,6 +262,7 @@ public: void set_gcode_preview_travel_visible(bool visible); void set_gcode_preview_retractions_visible(bool visible); void set_gcode_preview_unretractions_visible(bool visible); + void set_gcode_preview_shells_visible(bool visible); // methods for handling regions PrintRegion* get_region(size_t idx) { return regions.at(idx); } diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index 96cbabbe9..553239a6f 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -348,7 +348,32 @@ void GLVolumeCollection::render_VBOs() const GLsizei n_triangles = GLsizei(std::min(volume->indexed_vertex_array.triangle_indices_size, volume->tverts_range.second - volume->tverts_range.first)); GLsizei n_quads = GLsizei(std::min(volume->indexed_vertex_array.quad_indices_size, volume->qverts_range.second - volume->qverts_range.first)); if (n_triangles + n_quads == 0) + { + if (_render_interleaved_only_volumes.enabled) + { + ::glDisableClientState(GL_VERTEX_ARRAY); + ::glDisableClientState(GL_NORMAL_ARRAY); + ::glEnable(GL_BLEND); + ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + if (color_id >= 0) + { + float color[4]; + ::memcpy((void*)color, (const void*)volume->color, 3 * sizeof(float)); + color[3] = _render_interleaved_only_volumes.alpha; + ::glUniform4fv(color_id, 1, (const GLfloat*)color); + } + else + ::glColor4f(volume->color[0], volume->color[1], volume->color[2], _render_interleaved_only_volumes.alpha); + + volume->render(); + + ::glDisable(GL_BLEND); + ::glEnableClientState(GL_VERTEX_ARRAY); + ::glEnableClientState(GL_NORMAL_ARRAY); + } continue; + } if (color_id >= 0) glUniform4fv(color_id, 1, (const GLfloat*)volume->color); else @@ -387,7 +412,23 @@ void GLVolumeCollection::render_legacy() const GLsizei n_triangles = GLsizei(std::min(volume->indexed_vertex_array.triangle_indices_size, volume->tverts_range.second - volume->tverts_range.first)); GLsizei n_quads = GLsizei(std::min(volume->indexed_vertex_array.quad_indices_size, volume->qverts_range.second - volume->qverts_range.first)); if (n_triangles + n_quads == 0) + { + if (_render_interleaved_only_volumes.enabled) + { + ::glDisableClientState(GL_VERTEX_ARRAY); + ::glDisableClientState(GL_NORMAL_ARRAY); + ::glEnable(GL_BLEND); + ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + ::glColor4f(volume->color[0], volume->color[1], volume->color[2], _render_interleaved_only_volumes.alpha); + volume->render(); + + ::glDisable(GL_BLEND); + ::glEnableClientState(GL_VERTEX_ARRAY); + ::glEnableClientState(GL_NORMAL_ARRAY); + } continue; + } glColor4f(volume->color[0], volume->color[1], volume->color[2], volume->color[3]); glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), volume->indexed_vertex_array.vertices_and_normals_interleaved.data() + 3); glNormalPointer(GL_FLOAT, 6 * sizeof(float), volume->indexed_vertex_array.vertices_and_normals_interleaved.data()); @@ -1314,6 +1355,9 @@ static inline std::vector parse_colors(const std::vector &sc void _3DScene::load_gcode_preview(const Print* print, GLVolumeCollection* volumes, const std::vector& str_tool_colors, bool use_VBOs) { + if ((print == nullptr) || (volumes == nullptr)) + return; + if (volumes->empty()) { std::vector tool_colors = parse_colors(str_tool_colors); @@ -1326,9 +1370,17 @@ void _3DScene::load_gcode_preview(const Print* print, GLVolumeCollection* volume _load_gcode_unretractions(*print, *volumes, use_VBOs); if (volumes->empty()) + { reset_legend_texture(); + volumes->set_render_interleaved_only_volumes(GLVolumeCollection::RenderInterleavedOnlyVolumes(false, 0.0f)); + } else + { _generate_legend_texture(*print, tool_colors); + + _load_shells(*print, *volumes, use_VBOs); + volumes->set_render_interleaved_only_volumes(GLVolumeCollection::RenderInterleavedOnlyVolumes(true, 0.25f)); + } } _update_gcode_volumes_visibility(*print, *volumes); @@ -2209,6 +2261,11 @@ void _3DScene::_update_gcode_volumes_visibility(const Print& print, GLVolumeColl volume->is_active = print.gcode_preview.unretraction.is_visible; break; } + case GCodePreviewData::Shell: + { + volume->is_active = print.gcode_preview.shell.is_visible; + break; + } default: { volume->is_active = false; @@ -2224,4 +2281,41 @@ void _3DScene::_generate_legend_texture(const Print& print, const std::vectormodel_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) + volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, config.wipe_tower_per_color_wipe * (extruders_count - 1), max_z, use_VBOs); +} + } diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index 2b7f2de47..44e5dbea3 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -309,6 +309,28 @@ public: class GLVolumeCollection { +public: + struct RenderInterleavedOnlyVolumes + { + bool enabled; + float alpha; // [0..1] + + RenderInterleavedOnlyVolumes() + : enabled(false) + , alpha(0.0f) + { + } + + RenderInterleavedOnlyVolumes(bool enabled, float alpha) + : enabled(enabled) + , alpha(alpha) + { + } + }; + +private: + RenderInterleavedOnlyVolumes _render_interleaved_only_volumes; + public: std::vector volumes; @@ -344,6 +366,8 @@ public: bool empty() const { return volumes.empty(); } void set_range(double low, double high) { for (GLVolume *vol : this->volumes) vol->set_range(low, high); } + void set_render_interleaved_only_volumes(const RenderInterleavedOnlyVolumes& render_interleaved_only_volumes) { _render_interleaved_only_volumes = render_interleaved_only_volumes; } + private: GLVolumeCollection(const GLVolumeCollection &other); GLVolumeCollection& operator=(const GLVolumeCollection &); @@ -359,6 +383,7 @@ class _3DScene Travel, Retraction, Unretraction, + Shell, Num_Geometry_Types }; @@ -457,6 +482,8 @@ private: static void _update_gcode_volumes_visibility(const Print& print, GLVolumeCollection& volumes); // generates the legend texture in dependence of the current shown view type static void _generate_legend_texture(const Print& print, 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/xsp/Print.xsp b/xs/xsp/Print.xsp index 4df4a5865..4f870df68 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -171,6 +171,7 @@ _constant() void set_gcode_preview_travel_visible(bool visible); void set_gcode_preview_retractions_visible(bool visible); void set_gcode_preview_unretractions_visible(bool visible); + void set_gcode_preview_shells_visible(bool visible); PrintRegionPtrs* regions() %code%{ RETVAL = &THIS->regions; %};