diff --git a/resources/shaders/gouraud.fs b/resources/shaders/gouraud.fs index 9edc8fa76..f6116eec7 100644 --- a/resources/shaders/gouraud.fs +++ b/resources/shaders/gouraud.fs @@ -8,10 +8,18 @@ varying vec2 intensity; varying vec3 delta_box_min; varying vec3 delta_box_max; +varying float world_z; + uniform vec4 uniform_color; +// x = min z, y = max z; +uniform vec2 z_range; + void main() { + if ((world_z < z_range.x) || (z_range.y < world_z)) + discard; + // if the fragment is outside the print volume -> use darker color vec3 color = (any(lessThan(delta_box_min, ZERO)) || any(greaterThan(delta_box_max, ZERO))) ? mix(uniform_color.rgb, ZERO, 0.3333) : uniform_color.rgb; gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + color * intensity.x, uniform_color.a); diff --git a/resources/shaders/gouraud.vs b/resources/shaders/gouraud.vs index ea7e46e79..84ae51391 100644 --- a/resources/shaders/gouraud.vs +++ b/resources/shaders/gouraud.vs @@ -34,6 +34,8 @@ varying vec2 intensity; varying vec3 delta_box_min; varying vec3 delta_box_max; +varying float world_z; + void main() { // First transform the normal into camera space and normalize the result. @@ -67,4 +69,5 @@ void main() } gl_Position = ftransform(); + world_z = vec3(print_box.volume_world_matrix * gl_Vertex).z; } diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 7d9673e36..342c02e21 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -942,6 +942,7 @@ void GLVolumeCollection::render_VBOs() const GLint current_program_id; ::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id); GLint color_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "uniform_color") : -1; + GLint z_range_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "z_range") : -1; GLint print_box_min_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.min") : -1; GLint print_box_max_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.max") : -1; GLint print_box_detection_id = (current_program_id > 0) ? glGetUniformLocation(current_program_id, "print_box.volume_detection") : -1; @@ -953,6 +954,9 @@ void GLVolumeCollection::render_VBOs() const if (print_box_max_id != -1) ::glUniform3fv(print_box_max_id, 1, (const GLfloat*)print_box_max); + if (z_range_id != -1) + ::glUniform2fv(z_range_id, 1, (const GLfloat*)z_range); + for (GLVolume *volume : this->volumes) { if (volume->layer_height_texture_data.can_use()) diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 62816893c..4c3cafcc2 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -506,6 +506,9 @@ class GLVolumeCollection float print_box_min[3]; float print_box_max[3]; + // z range for clipping in shaders + float z_range[2]; + public: GLVolumePtrs volumes; @@ -564,6 +567,8 @@ public: print_box_max[0] = max_x; print_box_max[1] = max_y; print_box_max[2] = max_z; } + void set_z_range(float min_z, float max_z) { z_range[0] = min_z; z_range[1] = max_z; } + // returns true if all the volumes are completely contained in the print volume // returns the containment state in the given out_state, if non-null bool check_outside_state(const DynamicPrintConfig* config, ModelInstance::EPrintVolumeState* out_state); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index ed36b4d45..d29948024 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3312,6 +3312,7 @@ GLCanvas3D::GLCanvas3D(wxGLCanvas* canvas) : m_canvas(canvas) , m_context(nullptr) , m_toolbar(*this) + , m_use_clipping_planes(false) , m_config(nullptr) , m_process(nullptr) , m_model(nullptr) @@ -3755,6 +3756,12 @@ void GLCanvas3D::render() _camera_tranform(); + if (m_use_clipping_planes) + { + ::glClipPlane(GL_CLIP_PLANE0, (GLdouble*)m_clipping_planes[0].get_data()); + ::glClipPlane(GL_CLIP_PLANE1, (GLdouble*)m_clipping_planes[1].get_data()); + } + GLfloat position_cam[4] = { 1.0f, 0.0f, 1.0f, 0.0f }; ::glLightfv(GL_LIGHT1, GL_POSITION, position_cam); GLfloat position_top[4] = { -0.5f, -0.5f, 1.0f, 0.0f }; @@ -5694,6 +5701,11 @@ void GLCanvas3D::_render_objects() const ::glDisable(GL_CULL_FACE); } + if (m_use_clipping_planes) + m_volumes.set_z_range(m_clipping_planes[0].get_data()[3], m_clipping_planes[1].get_data()[3]); + else + m_volumes.set_z_range(-FLT_MAX, FLT_MAX); + m_shader.start_using(); m_volumes.render_VBOs(); m_shader.stop_using(); @@ -5703,6 +5715,12 @@ void GLCanvas3D::_render_objects() const } else { + if (m_use_clipping_planes) + { + ::glEnable(GL_CLIP_PLANE0); + ::glEnable(GL_CLIP_PLANE1); + } + // do not cull backfaces to show broken geometry, if any if (m_picking_enabled) ::glDisable(GL_CULL_FACE); @@ -5711,6 +5729,12 @@ void GLCanvas3D::_render_objects() const if (m_picking_enabled) ::glEnable(GL_CULL_FACE); + + if (m_use_clipping_planes) + { + ::glDisable(GL_CLIP_PLANE0); + ::glDisable(GL_CLIP_PLANE1); + } } ::glDisable(GL_LIGHTING); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index c009247ec..4ecb9ea92 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -556,6 +556,31 @@ public: #endif // ENABLE_ENSURE_ON_BED_WHILE_SCALING }; + class ClippingPlane + { + double m_data[4]; + + public: + ClippingPlane() + { + m_data[0] = 0.0; + m_data[1] = 0.0; + m_data[2] = 1.0; + m_data[3] = 0.0; + } + + ClippingPlane(const Vec3d& direction, double offset) + { + Vec3d norm_dir = direction.normalized(); + m_data[0] = norm_dir(0); + m_data[1] = norm_dir(1); + m_data[2] = norm_dir(2); + m_data[3] = offset; + } + + const double* get_data() const { return m_data; } + }; + private: class Gizmos { @@ -703,6 +728,8 @@ private: Mouse m_mouse; mutable Gizmos m_gizmos; mutable GLToolbar m_toolbar; + ClippingPlane m_clipping_planes[2]; + bool m_use_clipping_planes; mutable GLVolumeCollection m_volumes; Selection m_selection; @@ -778,6 +805,13 @@ public: void set_axes_length(float length); + void set_clipping_plane(unsigned int id, const ClippingPlane& plane) + { + if (id < 2) + m_clipping_planes[id] = plane; + } + void set_use_clipping_planes(bool use) { m_use_clipping_planes = use; } + void set_color_by(const std::string& value); float get_camera_zoom() const; diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index 0e533134a..398ee3999 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -391,11 +391,7 @@ void Preview::create_double_slider() // sizer, m_canvas_widget m_canvas_widget->Bind(wxEVT_KEY_DOWN, &Preview::update_double_slider_from_canvas, this); - m_slider->Bind(wxEVT_SCROLL_CHANGED, [this](wxEvent& event) { - m_canvas->set_toolpaths_range(m_slider->GetLowerValueD() - 1e-6, m_slider->GetHigherValueD() + 1e-6); - if (IsShown()) - m_canvas_widget->Refresh(); - }); + m_slider->Bind(wxEVT_SCROLL_CHANGED, &Preview::on_sliders_scroll_changed, this); Bind(wxCUSTOMEVT_TICKSCHANGED, [this](wxEvent&) { auto& config = wxGetApp().preset_bundle->project_config; @@ -409,10 +405,10 @@ void Preview::update_double_slider(const std::vector& layers_z, bool for std::vector> values; fill_slider_values(values, layers_z); - const double z_low = m_slider->GetLowerValueD(); - const double z_high = m_slider->GetHigherValueD(); m_slider->SetMaxValue(layers_z.size() - 1); m_slider->SetSliderValues(values); + const double z_low = m_slider->GetLowerValueD(); + const double z_high = m_slider->GetHigherValueD(); const auto& config = wxGetApp().preset_bundle->project_config; const std::vector &ticks_from_config = (config.option("colorprint_heights"))->values; @@ -425,19 +421,10 @@ void Preview::update_double_slider(const std::vector& layers_z, bool for void Preview::fill_slider_values(std::vector> &values, const std::vector &layers_z) { - std::vector layers_all_z = m_canvas->get_current_print_zs(false); - if (layers_all_z.size() == layers_z.size()) - for (int i = 0; i < layers_z.size(); i++) - values.push_back(std::pair(i + 1, layers_z[i])); - else if (layers_all_z.size() > layers_z.size()) { - int cur_id = 0; - for (int i = 0; i < layers_z.size(); i++) - for (int j = cur_id; j < layers_all_z.size(); j++) - if (layers_z[i] - 1e-6 < layers_all_z[j] && layers_all_z[j] < layers_z[i] + 1e-6) { - values.push_back(std::pair(j + 1, layers_z[i])); - cur_id = j; - break; - } + values.clear(); + for (int i = 0; i < layers_z.size(); ++i) + { + values.push_back(std::pair(i + 1, layers_z[i])); } // All ticks that would end up outside the slider range should be erased. @@ -626,12 +613,13 @@ void Preview::load_print_as_sla() std::set zs; for (const SLAPrintObject* obj : print->objects()) { + double shift_z = obj->get_current_elevation(); if (obj->is_step_done(slaposIndexSlices)) { const SLAPrintObject::SliceIndex& index = obj->get_slice_index(); for (const SLAPrintObject::SliceIndex::value_type& id : index) { - zs.insert(id.second.scale_back(id.first)); + zs.insert(shift_z + id.second.scale_back(id.first)); } } } @@ -645,7 +633,6 @@ void Preview::load_print_as_sla() if (IsShown()) { - std::cout << "Preview::load_print_as_sla()" << std::endl; m_canvas->load_sla_preview(); show_hide_ui_elements("none"); @@ -660,5 +647,26 @@ void Preview::load_print_as_sla() } } +void Preview::on_sliders_scroll_changed(wxEvent& event) +{ + if (IsShown()) + { + PrinterTechnology tech = m_process->current_printer_technology(); + if (tech == ptFFF) + { + m_canvas->set_toolpaths_range(m_slider->GetLowerValueD() - 1e-6, m_slider->GetHigherValueD() + 1e-6); + m_canvas_widget->Refresh(); + m_canvas->set_use_clipping_planes(false); + } + else if (tech == ptSLA) + { + m_canvas->set_clipping_plane(0, GLCanvas3D::ClippingPlane(Vec3d(0.0, 0.0, 1.0), m_slider->GetLowerValueD() - 1e-6)); + m_canvas->set_clipping_plane(1, GLCanvas3D::ClippingPlane(Vec3d(0.0, 0.0, -1.0), m_slider->GetHigherValueD() + 1e-6)); + m_canvas->set_use_clipping_planes(true); + m_canvas_widget->Refresh(); + } + } +} + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GUI_Preview.hpp b/src/slic3r/GUI/GUI_Preview.hpp index 902ead38d..bb6bfc4f6 100644 --- a/src/slic3r/GUI/GUI_Preview.hpp +++ b/src/slic3r/GUI/GUI_Preview.hpp @@ -110,6 +110,9 @@ private: void load_print_as_fff(); void load_print_as_sla(); + + void on_sliders_scroll_changed(wxEvent& event); + }; } // namespace GUI diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 8791e815b..bb4441bf2 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -1889,6 +1889,7 @@ void Plater::priv::update_sla_scene() this->schedule_background_process(); this->canvas3D->reload_scene(true); delayed_scene_refresh = false; + this->preview->reload_print(); } void Plater::priv::reload_from_disk() diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 5cd2564ed..d861aca5a 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -1854,6 +1854,8 @@ void PrusaDoubleSlider::correct_higher_value() void PrusaDoubleSlider::OnMotion(wxMouseEvent& event) { + bool action = false; + const wxClientDC dc(this); const wxPoint pos = event.GetLogicalPosition(dc); m_is_one_layer_icon_focesed = is_point_in_rect(pos, m_rect_one_layer_icon); @@ -1864,19 +1866,24 @@ void PrusaDoubleSlider::OnMotion(wxMouseEvent& event) if (m_selection == ssLower) { m_lower_value = get_value_from_position(pos.x, pos.y); correct_lower_value(); + action = true; } else if (m_selection == ssHigher) { m_higher_value = get_value_from_position(pos.x, pos.y); correct_higher_value(); + action = true; } } Refresh(); Update(); event.Skip(); - wxCommandEvent e(wxEVT_SCROLL_CHANGED); - e.SetEventObject(this); - ProcessWindowEvent(e); + if (action) + { + wxCommandEvent e(wxEVT_SCROLL_CHANGED); + e.SetEventObject(this); + ProcessWindowEvent(e); + } } void PrusaDoubleSlider::OnLeftUp(wxMouseEvent& event)