From 5ae2f8a467ccd41f0debd675ee38eee1edea6c62 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 29 Jan 2020 10:07:10 +0100 Subject: [PATCH 01/14] Function sla_trafo made accessible from outside SLAPrint.cpp unit --- src/libslic3r/SLAPrint.cpp | 8 ++++---- src/libslic3r/SLAPrint.hpp | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 4c10a44fa..23b4a8046 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -122,10 +122,10 @@ void SLAPrint::clear() } // Transformation without rotation around Z and without a shift by X and Y. -static Transform3d sla_trafo(const SLAPrint& p, const ModelObject &model_object) +Transform3d SLAPrint::sla_trafo(const ModelObject &model_object) const { - Vec3d corr = p.relative_correction(); + Vec3d corr = this->relative_correction(); ModelInstance &model_instance = *model_object.instances.front(); Vec3d offset = model_instance.get_offset(); @@ -376,7 +376,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con bool sla_trafo_differs = model_object.instances.empty() != model_object_new.instances.empty() || (! model_object.instances.empty() && - (! sla_trafo(*this, model_object).isApprox(sla_trafo(*this, model_object_new)) || + (! sla_trafo(model_object).isApprox(sla_trafo(model_object_new)) || model_object.instances.front()->is_left_handed() != model_object_new.instances.front()->is_left_handed())); if (model_parts_differ || sla_trafo_differs) { // The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects. @@ -453,7 +453,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con // FIXME: this invalidates the transformed mesh in SLAPrintObject // which is expensive to calculate (especially the raw_mesh() call) - print_object->set_trafo(sla_trafo(*this, model_object), model_object.instances.front()->is_left_handed()); + print_object->set_trafo(sla_trafo(model_object), model_object.instances.front()->is_left_handed()); print_object->set_instances(std::move(new_instances)); diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 771ca0bcd..871fb3de4 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -421,6 +421,9 @@ public: // Extracted value from the configuration objects Vec3d relative_correction() const; + // Return sla tansformation for a given model_object + Transform3d sla_trafo(const ModelObject &model_object) const; + std::string output_filename(const std::string &filename_base = std::string()) const override; const SLAPrintStatistics& print_statistics() const { return m_print_statistics; } From 76927ce3995c94b28d45b07c32926c867134453d Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 29 Jan 2020 10:07:59 +0100 Subject: [PATCH 02/14] REVERT LATER: TEMPORARILY MANGLED reload_scene FUNCTION This commit horribly cripples reload_scene function just to update volumes in scene so that Hollowing and SLASupport gizmos can be updated to the new logic It should be later reverted and the same be achieved in a better way --- src/slic3r/GUI/GLCanvas3D.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 8805dc92c..32d359429 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1930,6 +1930,8 @@ void GLCanvas3D::mirror_selection(Axis axis) // 5) Out of bed collision status & message overlay (texture) void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_refresh) { + force_full_scene_refresh = true; + if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr)) return; @@ -2189,9 +2191,28 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re } // Shift-up all volumes of the object so that it has the right elevation with respect to the print bed - for (GLVolume* volume : m_volumes.volumes) + for (GLVolume* volume : m_volumes.volumes) { if (volume->object_idx() < (int)m_model->objects.size() && m_model->objects[volume->object_idx()]->instances[volume->instance_idx()]->is_printable()) volume->set_sla_shift_z(shift_zs[volume->object_idx()]); + + // Just an experiment for now - replace the mesh with a hollowed one. + for (size_t po_idx=0; po_idxobjects().size(); ++po_idx) { + const SLAPrintObject* po = sla_print->objects()[po_idx]; + if (po_idx != volume->composite_id.object_id || volume->composite_id.volume_id < 0) + continue; + if (po->is_step_done(slaposHollowing)) { + TriangleMesh mesh = po->get_mesh(slaposHollowing); + if (mesh.empty()) + continue; + Transform3d t = sla_print->sla_trafo(*m_model->objects[volume->object_idx()]); + mesh.transform(t.inverse()); + GLIndexedVertexArray iva; + iva.load_mesh(mesh); + volume->indexed_vertex_array = iva; + volume->finalize_geometry(true); + } + } + } } if (printer_technology == ptFFF && m_config->has("nozzle_diameter")) From 46fdce116922368613ff01786fc21f0c650ef1f1 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 28 Jan 2020 10:20:37 +0100 Subject: [PATCH 03/14] SLA gizmos can now fetch hollowed and drilled mesh from the backend --- src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 51 +++++++++++ src/slic3r/GUI/Gizmos/GLGizmoBase.hpp | 12 ++- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 96 ++++++-------------- src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp | 2 - src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 20 ++-- 5 files changed, 99 insertions(+), 82 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 7dce249f2..bde54a0d2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -4,6 +4,9 @@ #include #include "slic3r/GUI/GUI_App.hpp" +#include "slic3r/GUI/GLCanvas3D.hpp" +#include "libslic3r/SLAPrint.hpp" +#include "slic3r/GUI/MeshUtils.hpp" @@ -302,5 +305,53 @@ unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char gr return b; } + + +bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas) +{ + if (! m_model_object) + return false; + + int old_po_idx = m_print_object_idx; + + // First we need a pointer to the respective SLAPrintObject. The index into objects vector is + // cached so we don't have todo it on each render. We only search for the po if needed: + if (m_print_object_idx < 0 || (int)canvas.sla_print()->objects().size() != m_print_objects_count) { + m_print_objects_count = canvas.sla_print()->objects().size(); + m_print_object_idx = -1; + for (const SLAPrintObject* po : canvas.sla_print()->objects()) { + ++m_print_object_idx; + if (po->model_object()->id() == m_model_object->id()) + break; + } + } + + if (m_print_object_idx < 0) + return old_po_idx != m_print_object_idx; + + m_mesh = nullptr; + // Load either the model_object mesh, or one provided by the backend + // This mesh does not account for the possible Z up SLA offset. + const SLAPrintObject* po = canvas.sla_print()->objects()[m_print_object_idx]; + + if (po->is_step_done(slaposHollowing)) + m_mesh = &po->get_mesh_to_print(); + else + m_mesh = &m_model_object->volumes.front()->mesh(); + + m_model_object_id = m_model_object->id(); + + if (m_mesh != m_old_mesh) { + m_mesh_raycaster.reset(new MeshRaycaster(*m_mesh)); + m_object_clipper.reset(); + m_supports_clipper.reset(); + m_old_mesh = m_mesh; + return true; + } + return false; +} + + + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index 9479174fb..0ff00a169 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -31,6 +31,7 @@ static const float CONSTRAINED_COLOR[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; class ImGuiWrapper; class CommonGizmosData; +class GLCanvas3D; class GLGizmoBase { @@ -189,9 +190,11 @@ class MeshClipper; class CommonGizmosData { public: const TriangleMesh* mesh() const { - return (! m_mesh ? nullptr : (m_cavity_mesh ? m_cavity_mesh.get() : m_mesh)); + return (! m_mesh ? nullptr : m_mesh); //(m_cavity_mesh ? m_cavity_mesh.get() : m_mesh)); } + bool update_from_backend(GLCanvas3D& canvas); + ModelObject* m_model_object = nullptr; @@ -200,8 +203,8 @@ public: std::unique_ptr m_object_clipper; std::unique_ptr m_supports_clipper; - std::unique_ptr m_cavity_mesh; - std::unique_ptr m_volume_with_cavity; + //std::unique_ptr m_cavity_mesh; + //std::unique_ptr m_volume_with_cavity; int m_active_instance = -1; float m_active_instance_bb_radius = 0; @@ -209,6 +212,9 @@ public: int m_print_object_idx = -1; int m_print_objects_count = -1; int m_old_timestamp = -1; + +private: + const TriangleMesh* m_old_mesh; }; } // namespace GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 042298274..51bc1b34f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -69,24 +69,24 @@ void GLGizmoHollow::set_sla_support_data(ModelObject* model_object, const Select || m_c->m_active_instance != selection.get_instance_idx()) { m_c->m_model_object = model_object; m_c->m_print_object_idx = -1; + m_c->m_mesh_raycaster.reset(); m_c->m_active_instance = selection.get_instance_idx(); something_changed = true; } - if (model_object && something_changed && selection.is_from_single_instance()) + if (model_object + && selection.is_from_single_instance() + && (m_c->update_from_backend(m_parent) || something_changed)) { // Cache the bb - it's needed for dealing with the clipping plane quite often // It could be done inside update_mesh but one has to account for scaling of the instance. m_c->m_active_instance_bb_radius = m_c->m_model_object->instance_bounding_box(m_c->m_active_instance).radius(); - if (is_mesh_update_necessary()) { - update_mesh(); - reload_cache(); - } + reload_cache(); if (m_state == On) { m_parent.toggle_model_objects_visibility(false); - m_parent.toggle_model_objects_visibility(! m_c->m_cavity_mesh, m_c->m_model_object, m_c->m_active_instance); + m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance); m_parent.toggle_sla_auxiliaries_visibility(m_show_supports, m_c->m_model_object, m_c->m_active_instance); } else @@ -109,8 +109,8 @@ void GLGizmoHollow::on_render() const return; } - if (! m_c->m_mesh) - const_cast(this)->update_mesh(); + // !!! is it necessary? + const_cast(this)->m_c->update_from_backend(m_parent); glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_DEPTH_TEST)); @@ -132,7 +132,7 @@ void GLGizmoHollow::on_render() const void GLGizmoHollow::render_hollowed_mesh() const { - if (m_c->m_volume_with_cavity) { + /*if (m_c->m_volume_with_cavity) { m_c->m_volume_with_cavity->set_sla_shift_z(m_z_shift); m_parent.get_shader().start_using(); @@ -148,14 +148,13 @@ void GLGizmoHollow::render_hollowed_mesh() const m_c->m_volume_with_cavity->set_instance_transformation(m_c->m_model_object->instances[size_t(m_c->m_active_instance)]->get_transformation()); m_c->m_volume_with_cavity->render(color_id, print_box_detection_id, print_box_worldmatrix_id); m_parent.get_shader().stop_using(); - } + }*/ } - void GLGizmoHollow::render_clipping_plane(const Selection& selection) const { - if (m_clipping_plane_distance == 0.f || m_c->mesh()->empty()) + if (m_clipping_plane_distance == 0.f) return; // Get transformation of the instance @@ -182,17 +181,9 @@ void GLGizmoHollow::render_clipping_plane(const Selection& selection) const // Next, ask the backend if supports are already calculated. If so, we are gonna cut them too. - // First we need a pointer to the respective SLAPrintObject. The index into objects vector is - // cached so we don't have todo it on each render. We only search for the po if needed: - if (m_c->m_print_object_idx < 0 || (int)m_parent.sla_print()->objects().size() != m_c->m_print_objects_count) { - m_c->m_print_objects_count = m_parent.sla_print()->objects().size(); - m_c->m_print_object_idx = -1; - for (const SLAPrintObject* po : m_parent.sla_print()->objects()) { - ++m_c->m_print_object_idx; - if (po->model_object()->id() == m_c->m_model_object->id()) - break; - } - } + if (m_c->m_print_object_idx < 0) + m_c->update_from_backend(m_parent); + if (m_c->m_print_object_idx >= 0) { const SLAPrintObject* print_object = m_parent.sla_print()->objects()[m_c->m_print_object_idx]; @@ -355,47 +346,13 @@ bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const -bool GLGizmoHollow::is_mesh_update_necessary() const -{ - return ((m_state == On) && (m_c->m_model_object != nullptr) && !m_c->m_model_object->instances.empty()) - && ((m_c->m_model_object->id() != m_c->m_model_object_id) || ! m_c->m_mesh); -} - - - -void GLGizmoHollow::update_mesh() -{ - if (! m_c->m_model_object) - return; - - wxBusyCursor wait; - // this way we can use that mesh directly. - // This mesh does not account for the possible Z up SLA offset. - m_c->m_mesh = &m_c->m_model_object->volumes.front()->mesh(); - - // If this is different mesh than last time - if (m_c->m_model_object_id != m_c->m_model_object->id()) { - m_c->m_cavity_mesh.reset(); // dump the cavity - m_c->m_volume_with_cavity.reset(); - m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance); - m_c->m_mesh_raycaster.reset(); - } - - if (! m_c->m_mesh_raycaster) - m_c->m_mesh_raycaster.reset(new MeshRaycaster(*m_c->mesh())); - - m_c->m_model_object_id = m_c->m_model_object->id(); -} - - - // Unprojects the mouse position on the mesh and saves hit point and normal of the facet into pos_and_normal // Return false if no intersection was found, true otherwise. bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pair& pos_and_normal) { // if the gizmo doesn't have the V, F structures for igl, calculate them first: - if (! m_c->m_mesh_raycaster) - update_mesh(); + // !!! is it really necessary? + m_c->update_from_backend(m_parent); const Camera& camera = m_parent.get_camera(); const Selection& selection = m_parent.get_selection(); @@ -605,7 +562,7 @@ void GLGizmoHollow::update_mesh_raycaster(std::unique_ptr &&rc) { m_c->m_mesh_raycaster = std::move(rc); m_c->m_object_clipper.reset(); - m_c->m_volume_with_cavity.reset(); + //m_c->m_volume_with_cavity.reset(); } void GLGizmoHollow::hollow_mesh(bool postpone_error_messages) @@ -622,7 +579,7 @@ void GLGizmoHollow::hollow_mesh(bool postpone_error_messages) void GLGizmoHollow::update_hollowed_mesh(std::unique_ptr &&mesh) { // Called from Plater when the UI job finishes - m_c->m_cavity_mesh = std::move(mesh); + /*m_c->m_cavity_mesh = std::move(mesh); if(m_c->m_cavity_mesh) { // First subtract the holes: @@ -668,7 +625,7 @@ void GLGizmoHollow::update_hollowed_mesh(std::unique_ptr &&mesh) if (m_clipping_plane_distance == 0.f) { m_clipping_plane_distance = 0.5f; update_clipping_plane(); - } + }*/ } std::vector> GLGizmoHollow::get_config_options(const std::vector& keys) const @@ -745,12 +702,13 @@ RENDER_AGAIN: wxGetApp().obj_list()->update_and_show_object_settings_item(); } } - m_imgui->disabled_begin(! m_enable_hollowing); ImGui::SameLine(); if (m_imgui->button(m_desc["preview"])) hollow_mesh(); + m_imgui->disabled_begin(! m_enable_hollowing); + std::vector opts_keys = {"hollowing_min_thickness", "hollowing_quality", "hollowing_closing_distance"}; auto opts = get_config_options(opts_keys); auto* offset_cfg = static_cast(opts[0].first); @@ -995,17 +953,17 @@ void GLGizmoHollow::on_set_state() if (m_state == On && m_old_state != On) { // the gizmo was just turned on //Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on"))); - if (is_mesh_update_necessary()) - update_mesh(); + m_c->update_from_backend(m_parent); // we'll now reload support points: if (m_c->m_model_object) reload_cache(); m_parent.toggle_model_objects_visibility(false); - if (m_c->m_model_object) - m_parent.toggle_model_objects_visibility(! m_c->m_cavity_mesh, m_c->m_model_object, m_c->m_active_instance); - m_parent.toggle_sla_auxiliaries_visibility(m_show_supports, m_c->m_model_object, m_c->m_active_instance); + if (m_c->m_model_object) { + m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance); + m_parent.toggle_sla_auxiliaries_visibility(m_show_supports, m_c->m_model_object, m_c->m_active_instance); + } // Set default head diameter from config. //const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config; @@ -1128,6 +1086,8 @@ void GLGizmoHollow::reload_cache() void GLGizmoHollow::update_clipping_plane(bool keep_normal) const { + if (! m_c->m_model_object) + return; Vec3d normal = (keep_normal && m_clipping_plane->get_normal() != Vec3d::Zero() ? m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward()); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp index 79b0a6929..617d0b2e6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp @@ -53,8 +53,6 @@ private: void render_points(const Selection& selection, bool picking = false) const; void render_clipping_plane(const Selection& selection) const; void render_hollowed_mesh() const; - bool is_mesh_update_necessary() const; - void update_mesh(); void hollow_mesh(bool postpone_error_messages = false); bool unsaved_changes() const; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index c6e0d9007..f63980d93 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -63,6 +63,8 @@ bool GLGizmoSlaSupports::on_init() void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const Selection& selection) { + return; + if (! model_object || selection.is_empty()) { m_c->m_model_object = nullptr; return; @@ -87,7 +89,7 @@ void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const S m_c->m_active_instance_bb_radius = m_c->m_model_object->instance_bounding_box(m_c->m_active_instance).radius(); if (m_state == On) { m_parent.toggle_model_objects_visibility(false); - m_parent.toggle_model_objects_visibility(! m_c->m_cavity_mesh, m_c->m_model_object, m_c->m_active_instance); + m_parent.toggle_model_objects_visibility(/*! m_c->m_cavity_mesh*/ true, m_c->m_model_object, m_c->m_active_instance); m_parent.toggle_sla_auxiliaries_visibility(! m_editing_mode, m_c->m_model_object, m_c->m_active_instance); } else @@ -143,7 +145,7 @@ void GLGizmoSlaSupports::on_render() const void GLGizmoSlaSupports::render_hollowed_mesh() const { - if (m_c->m_volume_with_cavity) { + /*if (m_c->m_volume_with_cavity) { m_c->m_volume_with_cavity->set_sla_shift_z(m_z_shift); m_parent.get_shader().start_using(); @@ -159,7 +161,7 @@ void GLGizmoSlaSupports::render_hollowed_mesh() const m_c->m_volume_with_cavity->set_instance_transformation(m_c->m_model_object->instances[size_t(m_c->m_active_instance)]->get_transformation()); m_c->m_volume_with_cavity->render(color_id, print_box_detection_id, print_box_worldmatrix_id); m_parent.get_shader().stop_using(); - } + }*/ } @@ -359,7 +361,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) } // Now render the drain holes: - if (! m_c->m_cavity_mesh) { + /*if (! m_c->m_cavity_mesh) { render_color[0] = 0.7f; render_color[1] = 0.7f; render_color[2] = 0.7f; @@ -394,7 +396,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) glFrontFace(GL_CCW); glsafe(::glPopMatrix()); } - } + }*/ if (!picking) glsafe(::glDisable(GL_LIGHTING)); @@ -467,14 +469,14 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pairm_cavity_mesh) { + /*if (! m_c->m_cavity_mesh) { for (const sla::DrainHole& hole : m_c->m_model_object->sla_drain_holes) { if (hole.is_inside(hit)) { in_hole = true; break; } } - } + }*/ if (! in_hole) { // Return both the point and the facet normal. pos_and_normal = std::make_pair(hit, normal); @@ -1051,7 +1053,7 @@ void GLGizmoSlaSupports::on_set_state() reload_cache(); m_parent.toggle_model_objects_visibility(false); - if (m_c->m_model_object && ! m_c->m_cavity_mesh) + if (m_c->m_model_object /*&& ! m_c->m_cavity_mesh*/) m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance); m_parent.toggle_sla_auxiliaries_visibility(! m_editing_mode, m_c->m_model_object, m_c->m_active_instance); @@ -1087,7 +1089,7 @@ void GLGizmoSlaSupports::on_set_state() m_its = nullptr; m_c->m_object_clipper.reset(); m_c->m_supports_clipper.reset(); - m_c->m_mesh_raycaster.reset(); + //m_c->m_mesh_raycaster.reset(); } } m_old_state = m_state; From 3f73261fdb2653ca304210dc3e4766f46fa568e0 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Tue, 28 Jan 2020 12:41:48 +0100 Subject: [PATCH 04/14] Fixed transformation of the hollowed mesh to be used at frontend Common gizmos data update is called from GLGizmoManager --- src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 23 +++++++++++++------- src/slic3r/GUI/Gizmos/GLGizmoBase.hpp | 1 + src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 6 +++-- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 3 +++ src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 3 +++ 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index bde54a0d2..e75315744 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -326,18 +326,24 @@ bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas) } } - if (m_print_object_idx < 0) - return old_po_idx != m_print_object_idx; - m_mesh = nullptr; // Load either the model_object mesh, or one provided by the backend // This mesh does not account for the possible Z up SLA offset. - const SLAPrintObject* po = canvas.sla_print()->objects()[m_print_object_idx]; + // The backend mesh needs to be transformed and because a pointer to it is + // saved, a copy is stored as a member (FIXME) + if (m_print_object_idx >=0) { + const SLAPrintObject* po = canvas.sla_print()->objects()[m_print_object_idx]; + if (po->is_step_done(slaposHollowing)) { + m_backend_mesh_transformed = po->get_mesh_to_print(); + m_backend_mesh_transformed.transform(canvas.sla_print()->sla_trafo(*m_model_object).inverse()); + m_mesh = &m_backend_mesh_transformed; + } + } - if (po->is_step_done(slaposHollowing)) - m_mesh = &po->get_mesh_to_print(); - else + if (! m_mesh) { m_mesh = &m_model_object->volumes.front()->mesh(); + m_backend_mesh_transformed.clear(); + } m_model_object_id = m_model_object->id(); @@ -348,7 +354,8 @@ bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas) m_old_mesh = m_mesh; return true; } - return false; + + return m_print_object_idx < 0 ? old_po_idx >=0 : false; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index 0ff00a169..c5a6d36aa 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -215,6 +215,7 @@ public: private: const TriangleMesh* m_old_mesh; + TriangleMesh m_backend_mesh_transformed; }; } // namespace GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 51bc1b34f..80695b468 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -76,8 +76,10 @@ void GLGizmoHollow::set_sla_support_data(ModelObject* model_object, const Select if (model_object && selection.is_from_single_instance() - && (m_c->update_from_backend(m_parent) || something_changed)) + && (something_changed)) { + m_c->update_from_backend(m_parent); + // Cache the bb - it's needed for dealing with the clipping plane quite often // It could be done inside update_mesh but one has to account for scaling of the instance. m_c->m_active_instance_bb_radius = m_c->m_model_object->instance_bounding_box(m_c->m_active_instance).radius(); @@ -580,7 +582,7 @@ void GLGizmoHollow::update_hollowed_mesh(std::unique_ptr &&mesh) { // Called from Plater when the UI job finishes /*m_c->m_cavity_mesh = std::move(mesh); - + if(m_c->m_cavity_mesh) { // First subtract the holes: if (! m_c->m_model_object->sla_drain_holes.empty()) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index f63980d93..db514c6e2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -1246,6 +1246,9 @@ void GLGizmoSlaSupports::reload_cache() bool GLGizmoSlaSupports::has_backend_supports() const { + if (! m_c->m_model_object) + return false; + // find SlaPrintObject with this ID for (const SLAPrintObject* po : m_parent.sla_print()->objects()) { if (po->model_object()->id() == m_c->m_model_object->id()) diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index ccc6369e4..acb74fffc 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -348,6 +348,9 @@ void GLGizmosManager::set_sla_support_data(ModelObject* model_object) if (!m_enabled || m_gizmos.empty()) return; + // Update common data for hollowing and sla support gizmos. + m_common_gizmos_data->update_from_backend(m_parent); + dynamic_cast(m_gizmos[SlaSupports].get())->set_sla_support_data(model_object, m_parent.get_selection()); dynamic_cast(m_gizmos[Hollow].get())->set_sla_support_data(model_object, m_parent.get_selection()); } From b41c6d7d64440e9a419441a179c3234081d3a7eb Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 29 Jan 2020 14:07:12 +0100 Subject: [PATCH 05/14] Refuse to drill a broken mesh Hole parameters defaults and limits changed a bit --- src/libslic3r/SLAPrintSteps.cpp | 11 +++++++++-- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/SLAPrintSteps.cpp b/src/libslic3r/SLAPrintSteps.cpp index f781814ae..44ef5fe45 100644 --- a/src/libslic3r/SLAPrintSteps.cpp +++ b/src/libslic3r/SLAPrintSteps.cpp @@ -80,6 +80,13 @@ SLAPrint::Steps::Steps(SLAPrint *print) void SLAPrint::Steps::hollow_model(SLAPrintObject &po) { po.m_hollowing_data.reset(); + bool drilling_needed = ! po.m_model_object->sla_drain_holes.empty(); + + // If the mesh is broken, stop immediately, even before hollowing. + if (drilling_needed && po.transformed_mesh().needed_repair()) + throw std::runtime_error(L("The mesh appears to be too broken " + "to drill holes into it reliably.")); + if (! po.m_config.hollowing_enable.getBool()) BOOST_LOG_TRIVIAL(info) << "Skipping hollowing step!"; else { @@ -104,7 +111,7 @@ void SLAPrint::Steps::hollow_model(SLAPrintObject &po) } // Drill holes into the hollowed/original mesh. - if (po.m_model_object->sla_drain_holes.empty()) + if (! drilling_needed) BOOST_LOG_TRIVIAL(info) << "Drilling skipped (no holes)."; else { BOOST_LOG_TRIVIAL(info) << "Drilling drainage holes."; @@ -116,7 +123,7 @@ void SLAPrint::Steps::hollow_model(SLAPrintObject &po) holes_mesh.merge(sla::to_triangle_mesh(holept.to_mesh())); holes_mesh.require_shared_vertices(); - MeshBoolean::self_union(holes_mesh); //FIXME-fix and use the cgal version + MeshBoolean::self_union(holes_mesh); // If there is no hollowed mesh yet, copy the original mesh. if (! po.m_hollowing_data) { diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 80695b468..078eda493 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -794,7 +794,7 @@ RENDER_AGAIN: // m_imgui->text(" "); // vertical gap ImGui::Separator(); - float diameter_upper_cap = 5.f; + float diameter_upper_cap = 15.; if (m_new_hole_radius > diameter_upper_cap) m_new_hole_radius = diameter_upper_cap; m_imgui->text(m_desc.at("hole_diameter")); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp index 617d0b2e6..5745b9393 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp @@ -58,7 +58,7 @@ private: bool m_show_supports = true; float m_new_hole_radius = 2.f; // Size of a new hole. - float m_new_hole_height = 5.f; + float m_new_hole_height = 6.f; mutable std::vector m_selected; // which holes are currently selected bool m_enable_hollowing = true; From b0aa937215ba44161b06d19b7c0db774760c7e60 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Wed, 29 Jan 2020 15:57:49 +0100 Subject: [PATCH 06/14] Trying to improve drilling stability by handling CGAL exceptions --- src/libslic3r/MeshBoolean.cpp | 13 +++++++++++-- src/libslic3r/SLAPrintSteps.cpp | 14 ++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/libslic3r/MeshBoolean.cpp b/src/libslic3r/MeshBoolean.cpp index 69db96d3f..734bfaca8 100644 --- a/src/libslic3r/MeshBoolean.cpp +++ b/src/libslic3r/MeshBoolean.cpp @@ -150,8 +150,17 @@ void minus(TriangleMesh &A, const TriangleMesh &B) triangle_mesh_to_cgal(B, meshB.m); CGALMesh meshResult; - CGALProc::corefine_and_compute_difference(meshA.m, meshB.m, meshResult.m); - + bool success = false; + try { + success = CGALProc::corefine_and_compute_difference(meshA.m, meshB.m, meshResult.m, + CGALParams::throw_on_self_intersection(true), CGALParams::throw_on_self_intersection(true)); + } + catch (const CGAL::Polygon_mesh_processing::Corefinement::Self_intersection_exception&) { + success = false; + } + if (! success) + throw std::runtime_error("CGAL corefine_and_compute_difference failed"); + A = cgal_to_triangle_mesh(meshResult.m); } diff --git a/src/libslic3r/SLAPrintSteps.cpp b/src/libslic3r/SLAPrintSteps.cpp index 44ef5fe45..8c0aac6fa 100644 --- a/src/libslic3r/SLAPrintSteps.cpp +++ b/src/libslic3r/SLAPrintSteps.cpp @@ -83,9 +83,9 @@ void SLAPrint::Steps::hollow_model(SLAPrintObject &po) bool drilling_needed = ! po.m_model_object->sla_drain_holes.empty(); // If the mesh is broken, stop immediately, even before hollowing. - if (drilling_needed && po.transformed_mesh().needed_repair()) - throw std::runtime_error(L("The mesh appears to be too broken " - "to drill holes into it reliably.")); + //if (drilling_needed && po.transformed_mesh().needed_repair()) + // throw std::runtime_error(L("The mesh appears to be too broken " + // "to drill holes into it reliably.")); if (! po.m_config.hollowing_enable.getBool()) BOOST_LOG_TRIVIAL(info) << "Skipping hollowing step!"; @@ -133,7 +133,13 @@ void SLAPrint::Steps::hollow_model(SLAPrintObject &po) TriangleMesh &hollowed_mesh = po.m_hollowing_data->hollow_mesh_with_holes; hollowed_mesh = po.get_mesh_to_print(); - MeshBoolean::cgal::minus(hollowed_mesh, holes_mesh); + try { + MeshBoolean::cgal::minus(hollowed_mesh, holes_mesh); + } + catch (const std::runtime_error& ex) { + throw std::runtime_error(L("Drilling holes into the mesh failed. " + "This is usually caused by broken model. Try to fix it first.")); + } hollowed_mesh.require_shared_vertices(); } } From 08dcbd027172492f27ed2103e2cba67d65e1d446 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 30 Jan 2020 14:12:52 +0100 Subject: [PATCH 07/14] Hollowing gizmo - most of updating now assumes that common data struct is updated properly --- src/slic3r/GUI/GLCanvas3D.cpp | 1 + src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 25 +++++++++++-- src/slic3r/GUI/Gizmos/GLGizmoBase.hpp | 4 ++- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 44 ++++++----------------- src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 2 +- 5 files changed, 39 insertions(+), 37 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 32d359429..c605c2928 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2208,6 +2208,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re mesh.transform(t.inverse()); GLIndexedVertexArray iva; iva.load_mesh(mesh); + volume->indexed_vertex_array.release_geometry(); volume->indexed_vertex_array = iva; volume->finalize_geometry(true); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index e75315744..0fc0cc94a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -307,9 +307,27 @@ unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char gr -bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas) +bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas, ModelObject* model_object) { - if (! m_model_object) + recent_update = false; + + if (m_model_object != model_object + || (model_object && m_model_object_id != model_object->id())) { + m_model_object = model_object; + m_print_object_idx = -1; + m_mesh_raycaster.reset(); + m_object_clipper.reset(); + m_supports_clipper.reset(); + if (m_model_object) { + m_active_instance = canvas.get_selection().get_instance_idx(); + m_active_instance_bb_radius = m_model_object->instance_bounding_box(m_active_instance).radius(); + } + + recent_update = true; + } + + + if (! m_model_object || ! canvas.get_selection().is_from_single_instance()) return false; int old_po_idx = m_print_object_idx; @@ -352,8 +370,11 @@ bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas) m_object_clipper.reset(); m_supports_clipper.reset(); m_old_mesh = m_mesh; + recent_update = true; return true; } + if (! recent_update) + recent_update = m_print_object_idx < 0 && old_po_idx >= 0; return m_print_object_idx < 0 ? old_po_idx >=0 : false; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index c5a6d36aa..85f87c8f5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -193,7 +193,9 @@ public: return (! m_mesh ? nullptr : m_mesh); //(m_cavity_mesh ? m_cavity_mesh.get() : m_mesh)); } - bool update_from_backend(GLCanvas3D& canvas); + bool update_from_backend(GLCanvas3D& canvas, ModelObject* model_object); + + bool recent_update = false; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 078eda493..1bb18a755 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -55,36 +55,12 @@ bool GLGizmoHollow::on_init() return true; } -void GLGizmoHollow::set_sla_support_data(ModelObject* model_object, const Selection& selection) +void GLGizmoHollow::set_sla_support_data(ModelObject*, const Selection&) { - if (! model_object || selection.is_empty()) { - m_c->m_model_object = nullptr; - return; - } + if (m_c->recent_update) { - bool something_changed = false; - - if (m_c->m_model_object != model_object - || m_c->m_model_object_id != model_object->id() - || m_c->m_active_instance != selection.get_instance_idx()) { - m_c->m_model_object = model_object; - m_c->m_print_object_idx = -1; - m_c->m_mesh_raycaster.reset(); - m_c->m_active_instance = selection.get_instance_idx(); - something_changed = true; - } - - if (model_object - && selection.is_from_single_instance() - && (something_changed)) - { - m_c->update_from_backend(m_parent); - - // Cache the bb - it's needed for dealing with the clipping plane quite often - // It could be done inside update_mesh but one has to account for scaling of the instance. - m_c->m_active_instance_bb_radius = m_c->m_model_object->instance_bounding_box(m_c->m_active_instance).radius(); - - reload_cache(); + if (m_c->m_model_object) + reload_cache(); if (m_state == On) { m_parent.toggle_model_objects_visibility(false); @@ -112,7 +88,7 @@ void GLGizmoHollow::on_render() const } // !!! is it necessary? - const_cast(this)->m_c->update_from_backend(m_parent); + //const_cast(this)->m_c->update_from_backend(m_parent, m_c->m_model_object); glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_DEPTH_TEST)); @@ -183,8 +159,8 @@ void GLGizmoHollow::render_clipping_plane(const Selection& selection) const // Next, ask the backend if supports are already calculated. If so, we are gonna cut them too. - if (m_c->m_print_object_idx < 0) - m_c->update_from_backend(m_parent); + //if (m_c->m_print_object_idx < 0) + // m_c->update_from_backend(m_parent, m_c->m_model_object); if (m_c->m_print_object_idx >= 0) { const SLAPrintObject* print_object = m_parent.sla_print()->objects()[m_c->m_print_object_idx]; @@ -352,9 +328,11 @@ bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const // Return false if no intersection was found, true otherwise. bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pair& pos_and_normal) { + if (! m_c->m_mesh_raycaster) + return false; // if the gizmo doesn't have the V, F structures for igl, calculate them first: // !!! is it really necessary? - m_c->update_from_backend(m_parent); + //m_c->update_from_backend(m_parent, m_c->m_model_object); const Camera& camera = m_parent.get_camera(); const Selection& selection = m_parent.get_selection(); @@ -955,7 +933,7 @@ void GLGizmoHollow::on_set_state() if (m_state == On && m_old_state != On) { // the gizmo was just turned on //Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on"))); - m_c->update_from_backend(m_parent); + //m_c->update_from_backend(m_parent, m_c->m_model_object); // we'll now reload support points: if (m_c->m_model_object) diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index acb74fffc..db459dd7d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -349,7 +349,7 @@ void GLGizmosManager::set_sla_support_data(ModelObject* model_object) return; // Update common data for hollowing and sla support gizmos. - m_common_gizmos_data->update_from_backend(m_parent); + m_common_gizmos_data->update_from_backend(m_parent, model_object); dynamic_cast(m_gizmos[SlaSupports].get())->set_sla_support_data(model_object, m_parent.get_selection()); dynamic_cast(m_gizmos[Hollow].get())->set_sla_support_data(model_object, m_parent.get_selection()); From 4f43c6d3f804fecbcf6ba09d5b25d41e3eeff5ca Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 30 Jan 2020 14:31:22 +0100 Subject: [PATCH 08/14] SlaSupports gizmo - most of updating now assumes that common data struct is updated properly --- src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 1 + src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 83 +++----------------- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp | 2 - 3 files changed, 14 insertions(+), 72 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 0fc0cc94a..92b990147 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -366,6 +366,7 @@ bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas, ModelObject* mode m_model_object_id = m_model_object->id(); if (m_mesh != m_old_mesh) { + wxBusyCursor wait; m_mesh_raycaster.reset(new MeshRaycaster(*m_mesh)); m_object_clipper.reset(); m_supports_clipper.reset(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index db514c6e2..c1c3c6d1c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -63,45 +63,22 @@ bool GLGizmoSlaSupports::on_init() void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const Selection& selection) { - return; - - if (! model_object || selection.is_empty()) { - m_c->m_model_object = nullptr; - return; - } - - bool something_changed = false; - - if (m_c->m_model_object != model_object - || m_c->m_model_object_id != model_object->id() - || m_c->m_active_instance != selection.get_instance_idx()) { - m_c->m_model_object = model_object; - m_c->m_print_object_idx = -1; - m_c->m_active_instance = selection.get_instance_idx(); - something_changed = true; - } - - if (model_object && selection.is_from_single_instance()) - { - // Cache the bb - it's needed for dealing with the clipping plane quite often - // It could be done inside update_mesh but one has to account for scaling of the instance. - if (something_changed) { - m_c->m_active_instance_bb_radius = m_c->m_model_object->instance_bounding_box(m_c->m_active_instance).radius(); - if (m_state == On) { - m_parent.toggle_model_objects_visibility(false); - m_parent.toggle_model_objects_visibility(/*! m_c->m_cavity_mesh*/ true, m_c->m_model_object, m_c->m_active_instance); - m_parent.toggle_sla_auxiliaries_visibility(! m_editing_mode, m_c->m_model_object, m_c->m_active_instance); - } - else - m_parent.toggle_model_objects_visibility(true, nullptr, -1); + if (m_c->recent_update) { + if (m_state == On) { + m_parent.toggle_model_objects_visibility(false); + m_parent.toggle_model_objects_visibility(/*! m_c->m_cavity_mesh*/ true, m_c->m_model_object, m_c->m_active_instance); + m_parent.toggle_sla_auxiliaries_visibility(! m_editing_mode, m_c->m_model_object, m_c->m_active_instance); } + else + m_parent.toggle_model_objects_visibility(true, nullptr, -1); - if (is_mesh_update_necessary()) { - update_mesh(); + disable_editing_mode(); + if (m_c->m_model_object) reload_cache(); - } + } - // If we triggered autogeneration before, check backend and fetch results if they are there + // If we triggered autogeneration before, check backend and fetch results if they are there + if (m_c->m_model_object) { if (m_c->m_model_object->sla_points_status == sla::PointsStatus::Generating) get_data_from_backend(); } @@ -122,9 +99,6 @@ void GLGizmoSlaSupports::on_render() const return; } - if (! m_its || ! m_c->m_mesh) - const_cast(this)->update_mesh(); - glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_DEPTH_TEST)); @@ -418,41 +392,12 @@ bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const -bool GLGizmoSlaSupports::is_mesh_update_necessary() const -{ - return ((m_state == On) && (m_c->m_model_object != nullptr) && !m_c->m_model_object->instances.empty()) - && ((m_c->m_model_object->id() != m_c->m_model_object_id) || m_its == nullptr); -} - - - -void GLGizmoSlaSupports::update_mesh() -{ - if (! m_c->m_model_object) - return; - - wxBusyCursor wait; - // this way we can use that mesh directly. - // This mesh does not account for the possible Z up SLA offset. - m_c->m_mesh = &m_c->m_model_object->volumes.front()->mesh(); - m_its = &m_c->m_mesh->its; - - // If this is different mesh than last time or if the AABB tree is uninitialized, recalculate it. - if (m_c->m_model_object_id != m_c->m_model_object->id() || ! m_c->m_mesh_raycaster) - m_c->m_mesh_raycaster.reset(new MeshRaycaster(*m_c->mesh())); - - m_c->m_model_object_id = m_c->m_model_object->id(); - disable_editing_mode(); -} - - // Unprojects the mouse position on the mesh and saves hit point and normal of the facet into pos_and_normal // Return false if no intersection was found, true otherwise. bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair& pos_and_normal) { - // if the gizmo doesn't have the V, F structures for igl, calculate them first: if (! m_c->m_mesh_raycaster) - update_mesh(); + return false; const Camera& camera = m_parent.get_camera(); const Selection& selection = m_parent.get_selection(); @@ -1045,8 +990,6 @@ void GLGizmoSlaSupports::on_set_state() if (m_state == On && m_old_state != On) { // the gizmo was just turned on Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on"))); - if (is_mesh_update_necessary()) - update_mesh(); // we'll now reload support points: if (m_c->m_model_object) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp index 3697e7af6..152979f83 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -91,8 +91,6 @@ private: void render_points(const Selection& selection, bool picking = false) const; void render_clipping_plane(const Selection& selection) const; void render_hollowed_mesh() const; - bool is_mesh_update_necessary() const; - void update_mesh(); bool unsaved_changes() const; bool m_lock_unique_islands = false; From a6f7fc93f411c4a773810ca5ab56ab88ec54aa18 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 30 Jan 2020 15:25:15 +0100 Subject: [PATCH 09/14] Gizmo updates - forget everything about the loaded mesh when an object is deselected --- src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 92b990147..463c681a6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -318,6 +318,9 @@ bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas, ModelObject* mode m_mesh_raycaster.reset(); m_object_clipper.reset(); m_supports_clipper.reset(); + m_old_mesh = nullptr; + m_mesh = nullptr; + m_backend_mesh_transformed.clear(); if (m_model_object) { m_active_instance = canvas.get_selection().get_instance_idx(); m_active_instance_bb_radius = m_model_object->instance_bounding_box(m_active_instance).radius(); From 9ef65b23d8627aa5d76140bf4829afad343adf96 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Thu, 30 Jan 2020 17:58:40 +0100 Subject: [PATCH 10/14] Implemented loading of hollowed SLA mesh into the scene in place of the normal mesh. WIP: The code is inefficient (it does not store the timestamp of the hollowed mesh, therefore it refreshes the hollowed mesh on each scene update) and if the hollowing gets invalidated, the original mesh is currently not being reloaded and the hollowed mesh is still visible. --- src/libslic3r/SLAPrint.cpp | 2 + src/slic3r/GUI/GLCanvas3D.cpp | 85 +++++++++++++++++------------------ 2 files changed, 42 insertions(+), 45 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 23b4a8046..1935e5e31 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -1103,6 +1103,8 @@ const ExPolygons &SliceRecord::get_slice(SliceOrigin o) const bool SLAPrintObject::has_mesh(SLAPrintObjectStep step) const { switch (step) { + case slaposHollowing: + return m_hollowing_data && !m_hollowing_data->hollow_mesh_with_holes.empty(); case slaposSupportTree: return ! this->support_mesh().empty(); case slaposPad: diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index c605c2928..fa3a25b79 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1930,8 +1930,6 @@ void GLCanvas3D::mirror_selection(Axis axis) // 5) Out of bed collision status & message overlay (texture) void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_refresh) { - force_full_scene_refresh = true; - if ((m_canvas == nullptr) || (m_config == nullptr) || (m_model == nullptr)) return; @@ -1971,8 +1969,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re }; // SLA steps to pull the preview meshes for. - typedef std::array SLASteps; - SLASteps sla_steps = { slaposSupportTree, slaposPad }; + typedef std::array SLASteps; + SLASteps sla_steps = { slaposHollowing, slaposSupportTree, slaposPad }; struct SLASupportState { std::array::value> step; }; @@ -2019,7 +2017,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re // Consider the DONE step without a valid mesh as invalid for the purpose // of mesh visualization. state.step[istep].state = PrintStateBase::INVALID; - else + else if (sla_steps[istep] != slaposHollowing) for (const ModelInstance* model_instance : print_object->model_object()->instances) // Only the instances, which are currently printable, will have the SLA support structures kept. // The instances outside the print bed will have the GLVolumes of their support structures released. @@ -2032,7 +2030,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re } std::sort(model_volume_state.begin(), model_volume_state.end(), model_volume_state_lower); std::sort(aux_volume_state.begin(), aux_volume_state.end(), model_volume_state_lower); - // Release all ModelVolume based GLVolumes not found in the current Model. + // Release all ModelVolume based GLVolumes not found in the current Model. Find the GLVolume of a hollowed mesh. for (size_t volume_id = 0; volume_id < m_volumes.volumes.size(); ++volume_id) { GLVolume* volume = m_volumes.volumes[volume_id]; ModelVolumeState key(volume); @@ -2114,6 +2112,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re if (it_old_volume != deleted_volumes.end() && it_old_volume->composite_id == it->composite_id) // If a volume changed its ObjectID, but it reuses a GLVolume's CompositeID, maintain its selection. map_glvolume_old_to_new[it_old_volume->volume_idx] = m_volumes.volumes.size(); + // Note the index of the loaded volume, so that we can reload the main model GLVolume with the hollowed mesh + // later in this function. + it->volume_idx = m_volumes.volumes.size(); m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by, m_initialized); m_volumes.volumes.back()->geometry_id = key.geometry_id; update_object_list = true; @@ -2163,57 +2164,51 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re int instance_idx = it - model_object->instances.begin(); for (size_t istep = 0; istep < sla_steps.size(); ++ istep) if (state.step[istep].state == PrintStateBase::DONE) { - ModelVolumeState key(state.step[istep].timestamp, instance.instance_id.id); - auto it = std::lower_bound(aux_volume_state.begin(), aux_volume_state.end(), key, model_volume_state_lower); - assert(it != aux_volume_state.end() && it->geometry_id == key.geometry_id); - if (it->new_geometry()) { - // This can be an SLA support structure that should not be rendered (in case someone used undo - // to revert to before it was generated). If that's the case, we should not generate anything. - if (model_object->sla_points_status != sla::PointsStatus::NoPoints) - instances[istep].emplace_back(std::pair(instance_idx, print_instance_idx)); - else - shift_zs[object_idx] = 0.; + if (sla_steps[istep] == slaposHollowing) { + // Check whether there is a main object mesh, which we may update with the hollowed mesh. + ModelVolumeState key(model_object->volumes.front()->id(), instance.instance_id); + auto it = std::lower_bound(model_volume_state.begin(), model_volume_state.end(), key, model_volume_state_lower); + assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id); + assert(!it->new_geometry()); + GLVolume& volume = *m_volumes.volumes[it->volume_idx]; + TriangleMesh mesh = print_object->get_mesh(slaposHollowing); + if (!mesh.empty()) { + Transform3d t = sla_print->sla_trafo(*m_model->objects[volume.object_idx()]); + mesh.transform(t.inverse()); + volume.indexed_vertex_array.release_geometry(); + volume.indexed_vertex_array.load_mesh(mesh); + volume.finalize_geometry(true); + } + } else { + // Check whether there is an existing auxiliary volume to be updated, or a new auxiliary volume to be created. + ModelVolumeState key(state.step[istep].timestamp, instance.instance_id.id); + auto it = std::lower_bound(aux_volume_state.begin(), aux_volume_state.end(), key, model_volume_state_lower); + assert(it != aux_volume_state.end() && it->geometry_id == key.geometry_id); + if (it->new_geometry()) { + // This can be an SLA support structure that should not be rendered (in case someone used undo + // to revert to before it was generated). If that's the case, we should not generate anything. + if (model_object->sla_points_status != sla::PointsStatus::NoPoints) + instances[istep].emplace_back(std::pair(instance_idx, print_instance_idx)); + else + shift_zs[object_idx] = 0.; + } else { + // Recycling an old GLVolume. Update the Object/Instance indices into the current Model. + m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx); + m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation()); + } } - else { - // Recycling an old GLVolume. Update the Object/Instance indices into the current Model. - m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx); - m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation()); - } } } -// // stores the current volumes count -// size_t volumes_count = m_volumes.volumes.size(); - for (size_t istep = 0; istep < sla_steps.size(); ++istep) if (!instances[istep].empty()) m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp, m_initialized); } // Shift-up all volumes of the object so that it has the right elevation with respect to the print bed - for (GLVolume* volume : m_volumes.volumes) { + for (GLVolume* volume : m_volumes.volumes) if (volume->object_idx() < (int)m_model->objects.size() && m_model->objects[volume->object_idx()]->instances[volume->instance_idx()]->is_printable()) volume->set_sla_shift_z(shift_zs[volume->object_idx()]); - - // Just an experiment for now - replace the mesh with a hollowed one. - for (size_t po_idx=0; po_idxobjects().size(); ++po_idx) { - const SLAPrintObject* po = sla_print->objects()[po_idx]; - if (po_idx != volume->composite_id.object_id || volume->composite_id.volume_id < 0) - continue; - if (po->is_step_done(slaposHollowing)) { - TriangleMesh mesh = po->get_mesh(slaposHollowing); - if (mesh.empty()) - continue; - Transform3d t = sla_print->sla_trafo(*m_model->objects[volume->object_idx()]); - mesh.transform(t.inverse()); - GLIndexedVertexArray iva; - iva.load_mesh(mesh); - volume->indexed_vertex_array.release_geometry(); - volume->indexed_vertex_array = iva; - volume->finalize_geometry(true); - } - } - } } if (printer_technology == ptFFF && m_config->has("nozzle_diameter")) From f28d0ebc1871e8fc3687e897a06a3cc10c0b87cf Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 3 Feb 2020 12:55:38 +0100 Subject: [PATCH 11/14] Implemented reload of original mesh volume in case the SLA hollowing step is no more valid. --- src/slic3r/GUI/3DScene.hpp | 57 +++++++++++++++------------ src/slic3r/GUI/GLCanvas3D.cpp | 74 +++++++++++++++++++---------------- 2 files changed, 72 insertions(+), 59 deletions(-) diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 5d559c246..aed907004 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -313,33 +313,38 @@ public: // Valid geometry_id should always be positive. std::pair geometry_id; // An ID containing the extruder ID (used to select color). - int extruder_id; - // Is this object selected? - bool selected; - // Is this object disabled from selection? - bool disabled; - // Is this object printable? - bool printable; - // Whether or not this volume is active for rendering - bool is_active; - // Whether or not to use this volume when applying zoom_to_volumes() - bool zoom_to_volumes; - // Wheter or not this volume is enabled for outside print volume detection in shader. - bool shader_outside_printer_detection_enabled; - // Wheter or not this volume is outside print volume. - bool is_outside; + int extruder_id; + + // Various boolean flags. + struct { + // Is this object selected? + bool selected : 1; + // Is this object disabled from selection? + bool disabled : 1; + // Is this object printable? + bool printable : 1; + // Whether or not this volume is active for rendering + bool is_active : 1; + // Whether or not to use this volume when applying zoom_to_volumes() + bool zoom_to_volumes : 1; + // Wheter or not this volume is enabled for outside print volume detection in shader. + bool shader_outside_printer_detection_enabled : 1; + // Wheter or not this volume is outside print volume. + bool is_outside : 1; + // Wheter or not this volume has been generated from a modifier + bool is_modifier : 1; + // Wheter or not this volume has been generated from the wipe tower + bool is_wipe_tower : 1; + // Wheter or not this volume has been generated from an extrusion path + bool is_extrusion_path : 1; + // Wheter or not to always render this volume using its own alpha + bool force_transparent : 1; + // Whether or not always use the volume's own color (not using SELECTED/HOVER/DISABLED/OUTSIDE) + bool force_native_color : 1; + }; + // Is mouse or rectangle selection over this object to select/deselect it ? - EHoverState hover; - // Wheter or not this volume has been generated from a modifier - bool is_modifier; - // Wheter or not this volume has been generated from the wipe tower - bool is_wipe_tower; - // Wheter or not this volume has been generated from an extrusion path - bool is_extrusion_path; - // Wheter or not to always render this volume using its own alpha - bool force_transparent; - // Whether or not always use the volume's own color (not using SELECTED/HOVER/DISABLED/OUTSIDE) - bool force_native_color; + EHoverState hover; // Interleaved triangles & normals with indexed triangles & quads. GLIndexedVertexArray indexed_vertex_array; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index fa3a25b79..e0c7a77a0 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -2143,8 +2143,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re const ModelObject *model_object = print_object->model_object(); // Find an index of the ModelObject int object_idx; - if (std::all_of(state.step.begin(), state.step.end(), [](const PrintStateBase::StateWithTimeStamp &state){ return state.state != PrintStateBase::DONE; })) - continue; // There may be new SLA volumes added to the scene for this print_object. // Find the object index of this print_object in the Model::objects list. auto it = std::find(sla_print->model().objects.begin(), sla_print->model().objects.end(), model_object); @@ -2163,39 +2161,49 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re assert(it != model_object->instances.end()); int instance_idx = it - model_object->instances.begin(); for (size_t istep = 0; istep < sla_steps.size(); ++ istep) - if (state.step[istep].state == PrintStateBase::DONE) { - if (sla_steps[istep] == slaposHollowing) { - // Check whether there is a main object mesh, which we may update with the hollowed mesh. - ModelVolumeState key(model_object->volumes.front()->id(), instance.instance_id); - auto it = std::lower_bound(model_volume_state.begin(), model_volume_state.end(), key, model_volume_state_lower); - assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id); - assert(!it->new_geometry()); - GLVolume& volume = *m_volumes.volumes[it->volume_idx]; - TriangleMesh mesh = print_object->get_mesh(slaposHollowing); - if (!mesh.empty()) { - Transform3d t = sla_print->sla_trafo(*m_model->objects[volume.object_idx()]); - mesh.transform(t.inverse()); - volume.indexed_vertex_array.release_geometry(); + if (sla_steps[istep] == slaposHollowing) { + // Hollowing is a special case, where the mesh from the backend is being loaded into the 1st volume of an instance, + // not into its own GLVolume. + // There shall always be such a GLVolume allocated. + ModelVolumeState key(model_object->volumes.front()->id(), instance.instance_id); + auto it = std::lower_bound(model_volume_state.begin(), model_volume_state.end(), key, model_volume_state_lower); + assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id); + assert(!it->new_geometry()); + GLVolume &volume = *m_volumes.volumes[it->volume_idx]; + if (! volume.offsets.empty() && state.step[istep].timestamp != volume.offsets.front()) { + // The backend either produced a new hollowed mesh, or it invalidated the one that the front end has seen. + volume.indexed_vertex_array.release_geometry(); + if (state.step[istep].state == PrintStateBase::DONE) { + TriangleMesh mesh = print_object->get_mesh(slaposHollowing); + assert(! mesh.empty()); + mesh.transform(sla_print->sla_trafo(*m_model->objects[volume.object_idx()]).inverse()); volume.indexed_vertex_array.load_mesh(mesh); - volume.finalize_geometry(true); - } + } else { + // Reload the original volume. + volume.indexed_vertex_array.load_mesh(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh()); + } + volume.finalize_geometry(true); + } + //FIXME it is an ugly hack to write the timestamp into the "offsets" field to not have to add another member variable + // to the GLVolume. We should refactor GLVolume significantly, so that the GLVolume will not contain member variables + // of various concenrs (model vs. 3D print path). + volume.offsets = { state.step[istep].timestamp }; + } else if (state.step[istep].state == PrintStateBase::DONE) { + // Check whether there is an existing auxiliary volume to be updated, or a new auxiliary volume to be created. + ModelVolumeState key(state.step[istep].timestamp, instance.instance_id.id); + auto it = std::lower_bound(aux_volume_state.begin(), aux_volume_state.end(), key, model_volume_state_lower); + assert(it != aux_volume_state.end() && it->geometry_id == key.geometry_id); + if (it->new_geometry()) { + // This can be an SLA support structure that should not be rendered (in case someone used undo + // to revert to before it was generated). If that's the case, we should not generate anything. + if (model_object->sla_points_status != sla::PointsStatus::NoPoints) + instances[istep].emplace_back(std::pair(instance_idx, print_instance_idx)); + else + shift_zs[object_idx] = 0.; } else { - // Check whether there is an existing auxiliary volume to be updated, or a new auxiliary volume to be created. - ModelVolumeState key(state.step[istep].timestamp, instance.instance_id.id); - auto it = std::lower_bound(aux_volume_state.begin(), aux_volume_state.end(), key, model_volume_state_lower); - assert(it != aux_volume_state.end() && it->geometry_id == key.geometry_id); - if (it->new_geometry()) { - // This can be an SLA support structure that should not be rendered (in case someone used undo - // to revert to before it was generated). If that's the case, we should not generate anything. - if (model_object->sla_points_status != sla::PointsStatus::NoPoints) - instances[istep].emplace_back(std::pair(instance_idx, print_instance_idx)); - else - shift_zs[object_idx] = 0.; - } else { - // Recycling an old GLVolume. Update the Object/Instance indices into the current Model. - m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx); - m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation()); - } + // Recycling an old GLVolume. Update the Object/Instance indices into the current Model. + m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx); + m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation()); } } } From 79da3a95e18bef9a3484737a818659191d577b98 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 31 Jan 2020 15:54:16 +0100 Subject: [PATCH 12/14] Clipping plane is now common for Hollowing and SLA supports gizmos --- src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 2 + src/slic3r/GUI/Gizmos/GLGizmoBase.hpp | 13 +++++ src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 53 +++++++++++--------- src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp | 6 +-- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp | 51 ++++++++++--------- src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp | 3 +- 6 files changed, 73 insertions(+), 55 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 463c681a6..653bfefb5 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -374,6 +374,8 @@ bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas, ModelObject* mode m_object_clipper.reset(); m_supports_clipper.reset(); m_old_mesh = m_mesh; + m_clipping_plane_distance = 0.f; + m_clipping_plane_distance_stash = 0.f; recent_update = true; return true; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp index 85f87c8f5..5cd3d9d84 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.hpp @@ -32,6 +32,7 @@ static const float CONSTRAINED_COLOR[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; class ImGuiWrapper; class CommonGizmosData; class GLCanvas3D; +class ClippingPlane; class GLGizmoBase { @@ -215,9 +216,21 @@ public: int m_print_objects_count = -1; int m_old_timestamp = -1; + float m_clipping_plane_distance = 0.f; + std::unique_ptr m_clipping_plane; + + void stash_clipping_plane() { + m_clipping_plane_distance_stash = m_clipping_plane_distance; + } + + void unstash_clipping_plane() { + m_clipping_plane_distance = m_clipping_plane_distance_stash; + } + private: const TriangleMesh* m_old_mesh; TriangleMesh m_backend_mesh_transformed; + float m_clipping_plane_distance_stash = 0.f; }; } // namespace GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 1bb18a755..3db5e1e13 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -22,7 +22,7 @@ GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filenam : GLGizmoBase(parent, icon_filename, sprite_id, cd) , m_quadric(nullptr) { - m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.)); + m_c->m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.)); m_quadric = ::gluNewQuadric(); if (m_quadric != nullptr) // using GLU_FILL does not work when the instance's transformation @@ -132,7 +132,7 @@ void GLGizmoHollow::render_hollowed_mesh() const void GLGizmoHollow::render_clipping_plane(const Selection& selection) const { - if (m_clipping_plane_distance == 0.f) + if (m_c->m_clipping_plane_distance == 0.f) return; // Get transformation of the instance @@ -154,7 +154,7 @@ void GLGizmoHollow::render_clipping_plane(const Selection& selection) const m_c->m_object_clipper.reset(new MeshClipper); m_c->m_object_clipper->set_mesh(*m_c->mesh()); } - m_c->m_object_clipper->set_plane(*m_clipping_plane); + m_c->m_object_clipper->set_plane(*m_c->m_clipping_plane); m_c->m_object_clipper->set_transformation(trafo); @@ -177,7 +177,7 @@ void GLGizmoHollow::render_clipping_plane(const Selection& selection) const m_c->m_supports_clipper->set_mesh(print_object->support_mesh()); m_c->m_old_timestamp = timestamp; } - m_c->m_supports_clipper->set_plane(*m_clipping_plane); + m_c->m_supports_clipper->set_plane(*m_c->m_clipping_plane); m_c->m_supports_clipper->set_transformation(supports_trafo); } else @@ -314,12 +314,12 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const { - if (m_clipping_plane_distance == 0.f) + if (m_c->m_clipping_plane_distance == 0.f) return false; Vec3d transformed_point = m_c->m_model_object->instances[m_c->m_active_instance]->get_transformation().get_matrix() * point; transformed_point(2) += m_z_shift; - return m_clipping_plane->is_point_clipped(transformed_point); + return m_c->m_clipping_plane->is_point_clipped(transformed_point); } @@ -343,7 +343,7 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pairm_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_clipping_plane.get())) { + if (m_c->m_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_c->m_clipping_plane.get())) { // Return both the point and the facet normal. pos_and_normal = std::make_pair(hit, normal); return true; @@ -429,7 +429,7 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos points_inside.push_back(points[idx].cast()); // Only select/deselect points that are actually visible - for (size_t idx : m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_clipping_plane.get())) + for (size_t idx : m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_c->m_clipping_plane.get())) { if (rectangle_status == GLSelectionRectangle::Deselect) unselect_point(points_idxs[idx]); @@ -483,13 +483,13 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos } if (action == SLAGizmoEventType::MouseWheelUp && control_down) { - m_clipping_plane_distance = std::min(1.f, m_clipping_plane_distance + 0.01f); + m_c->m_clipping_plane_distance = std::min(1.f, m_c->m_clipping_plane_distance + 0.01f); update_clipping_plane(true); return true; } if (action == SLAGizmoEventType::MouseWheelDown && control_down) { - m_clipping_plane_distance = std::max(0.f, m_clipping_plane_distance - 0.01f); + m_c->m_clipping_plane_distance = std::max(0.f, m_c->m_clipping_plane_distance - 0.01f); update_clipping_plane(true); return true; } @@ -602,8 +602,8 @@ void GLGizmoHollow::update_hollowed_mesh(std::unique_ptr &&mesh) m_c->m_mesh_raycaster.reset(new MeshRaycaster(*m_c->mesh())); } - if (m_clipping_plane_distance == 0.f) { - m_clipping_plane_distance = 0.5f; + if (m_c->m_clipping_plane_distance == 0.f) { + m_c->m_clipping_plane_distance = 0.5f; update_clipping_plane(); }*/ } @@ -638,10 +638,10 @@ std::vector> GLGizmoHollo ClippingPlane GLGizmoHollow::get_sla_clipping_plane() const { - if (!m_c->m_model_object || m_state == Off || m_clipping_plane_distance == 0.f) + if (!m_c->m_model_object || m_state == Off || m_c->m_clipping_plane_distance == 0.f) return ClippingPlane::ClipsNothing(); else - return ClippingPlane(-m_clipping_plane->get_normal(), m_clipping_plane->get_data()[3]); + return ClippingPlane(-m_c->m_clipping_plane->get_normal(), m_c->m_clipping_plane->get_data()[3]); } @@ -842,7 +842,7 @@ RENDER_AGAIN: // Following is rendered in both editing and non-editing mode: // m_imgui->text(""); ImGui::Separator(); - if (m_clipping_plane_distance == 0.f) + if (m_c->m_clipping_plane_distance == 0.f) m_imgui->text(m_desc.at("clipping_of_view")); else { if (m_imgui->button(m_desc.at("reset_direction"))) { @@ -854,7 +854,7 @@ RENDER_AGAIN: ImGui::SameLine(clipping_slider_left); ImGui::PushItemWidth(window_width - clipping_slider_left); - if (ImGui::SliderFloat(" ", &m_clipping_plane_distance, 0.f, 1.f, "%.2f")) + if (ImGui::SliderFloat(" ", &m_c->m_clipping_plane_distance, 0.f, 1.f, "%.2f")) update_clipping_plane(true); // make sure supports are shown/hidden as appropriate @@ -934,6 +934,8 @@ void GLGizmoHollow::on_set_state() if (m_state == On && m_old_state != On) { // the gizmo was just turned on //Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on"))); //m_c->update_from_backend(m_parent, m_c->m_model_object); + m_c->unstash_clipping_plane(); + update_clipping_plane(m_c->m_clipping_plane_distance != 0.f); // we'll now reload support points: if (m_c->m_model_object) @@ -952,8 +954,9 @@ void GLGizmoHollow::on_set_state() if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off //Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned off"))); m_parent.toggle_model_objects_visibility(true); - m_clipping_plane_distance = 0.f; - update_clipping_plane(); + m_c->stash_clipping_plane(); + m_c->m_clipping_plane_distance = 0.f; + update_clipping_plane(true); // Release clippers and the AABB raycaster. m_c->m_object_clipper.reset(); m_c->m_supports_clipper.reset(); @@ -998,8 +1001,8 @@ void GLGizmoHollow::on_stop_dragging() void GLGizmoHollow::on_load(cereal::BinaryInputArchive& ar) { - ar(m_clipping_plane_distance, - *m_clipping_plane, + ar(m_c->m_clipping_plane_distance, + *m_c->m_clipping_plane, m_c->m_model_object_id, m_new_hole_radius, m_new_hole_height, @@ -1012,8 +1015,8 @@ void GLGizmoHollow::on_load(cereal::BinaryInputArchive& ar) void GLGizmoHollow::on_save(cereal::BinaryOutputArchive& ar) const { - ar(m_clipping_plane_distance, - *m_clipping_plane, + ar(m_c->m_clipping_plane_distance, + *m_c->m_clipping_plane, m_c->m_model_object_id, m_new_hole_radius, m_new_hole_height, @@ -1068,12 +1071,12 @@ void GLGizmoHollow::update_clipping_plane(bool keep_normal) const { if (! m_c->m_model_object) return; - Vec3d normal = (keep_normal && m_clipping_plane->get_normal() != Vec3d::Zero() ? - m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward()); + Vec3d normal = (keep_normal && m_c->m_clipping_plane->get_normal() != Vec3d::Zero() ? + m_c->m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward()); const Vec3d& center = m_c->m_model_object->instances[m_c->m_active_instance]->get_offset() + Vec3d(0., 0., m_z_shift); float dist = normal.dot(center); - *m_clipping_plane = ClippingPlane(normal, (dist - (-m_c->m_active_instance_bb_radius) - m_clipping_plane_distance * 2*m_c->m_active_instance_bb_radius)); + *m_c->m_clipping_plane = ClippingPlane(normal, (dist - (-m_c->m_active_instance_bb_radius) - m_c->m_clipping_plane_distance * 2*m_c->m_active_instance_bb_radius)); m_parent.set_as_dirty(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp index 5745b9393..6264304b7 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp @@ -70,13 +70,9 @@ private: float m_closing_d_stash = 2.f; Vec3f m_hole_before_drag = Vec3f::Zero(); - sla::DrainHoles m_holes_stash; - - - float m_clipping_plane_distance = 0.f; - std::unique_ptr m_clipping_plane; + //std::unique_ptr m_clipping_plane; // This map holds all translated description texts, so they can be easily referenced during layout calculations // etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect. diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp index c1c3c6d1c..879a09da2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.cpp @@ -27,7 +27,7 @@ GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& ic , m_quadric(nullptr) , m_its(nullptr) { - m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.)); + m_c->m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.)); m_quadric = ::gluNewQuadric(); if (m_quadric != nullptr) // using GLU_FILL does not work when the instance's transformation @@ -142,7 +142,7 @@ void GLGizmoSlaSupports::render_hollowed_mesh() const void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const { - if (m_clipping_plane_distance == 0.f || m_c->m_mesh->empty()) + if (m_c->m_clipping_plane_distance == 0.f || m_c->m_mesh->empty()) return; // Get transformation of the instance @@ -164,7 +164,7 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const m_c->m_object_clipper.reset(new MeshClipper); m_c->m_object_clipper->set_mesh(*m_c->mesh()); } - m_c->m_object_clipper->set_plane(*m_clipping_plane); + m_c->m_object_clipper->set_plane(*m_c->m_clipping_plane); m_c->m_object_clipper->set_transformation(trafo); @@ -195,7 +195,7 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const m_c->m_supports_clipper->set_mesh(print_object->support_mesh()); m_c->m_old_timestamp = timestamp; } - m_c->m_supports_clipper->set_plane(*m_clipping_plane); + m_c->m_supports_clipper->set_plane(*m_c->m_clipping_plane); m_c->m_supports_clipper->set_transformation(supports_trafo); } else @@ -382,12 +382,12 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const { - if (m_clipping_plane_distance == 0.f) + if (m_c->m_clipping_plane_distance == 0.f) return false; Vec3d transformed_point = m_c->m_model_object->instances[m_c->m_active_instance]->get_transformation().get_matrix() * point; transformed_point(2) += m_z_shift; - return m_clipping_plane->is_point_clipped(transformed_point); + return m_c->m_clipping_plane->is_point_clipped(transformed_point); } @@ -408,7 +408,7 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pairm_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_clipping_plane.get())) { + if (m_c->m_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_c->m_clipping_plane.get())) { // Check whether the hit is in a hole bool in_hole = false; // In case the hollowed and drilled mesh is available, we can allow @@ -502,7 +502,7 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous points_inside.push_back(points[idx].cast()); // Only select/deselect points that are actually visible - for (size_t idx : m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_clipping_plane.get())) + for (size_t idx : m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_c->m_clipping_plane.get())) { if (rectangle_status == GLSelectionRectangle::Deselect) unselect_point(points_idxs[idx]); @@ -579,13 +579,13 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous } if (action == SLAGizmoEventType::MouseWheelUp && control_down) { - m_clipping_plane_distance = std::min(1.f, m_clipping_plane_distance + 0.01f); + m_c->m_clipping_plane_distance = std::min(1.f, m_c->m_clipping_plane_distance + 0.01f); update_clipping_plane(true); return true; } if (action == SLAGizmoEventType::MouseWheelDown && control_down) { - m_clipping_plane_distance = std::max(0.f, m_clipping_plane_distance - 0.01f); + m_c->m_clipping_plane_distance = std::max(0.f, m_c->m_clipping_plane_distance - 0.01f); update_clipping_plane(true); return true; } @@ -666,10 +666,10 @@ std::vector GLGizmoSlaSupports::get_config_options(const st ClippingPlane GLGizmoSlaSupports::get_sla_clipping_plane() const { - if (!m_c->m_model_object || m_state == Off || m_clipping_plane_distance == 0.f) + if (!m_c->m_model_object || m_state == Off || m_c->m_clipping_plane_distance == 0.f) return ClippingPlane::ClipsNothing(); else - return ClippingPlane(-m_clipping_plane->get_normal(), m_clipping_plane->get_data()[3]); + return ClippingPlane(-m_c->m_clipping_plane->get_normal(), m_c->m_clipping_plane->get_data()[3]); } @@ -891,7 +891,7 @@ RENDER_AGAIN: // Following is rendered in both editing and non-editing mode: ImGui::Separator(); - if (m_clipping_plane_distance == 0.f) + if (m_c->m_clipping_plane_distance == 0.f) { ImGui::AlignTextToFramePadding(); m_imgui->text(m_desc.at("clipping_of_view")); @@ -906,7 +906,7 @@ RENDER_AGAIN: ImGui::SameLine(clipping_slider_left); ImGui::PushItemWidth(window_width - clipping_slider_left); - if (ImGui::SliderFloat(" ", &m_clipping_plane_distance, 0.f, 1.f, "%.2f")) + if (ImGui::SliderFloat(" ", &m_c->m_clipping_plane_distance, 0.f, 1.f, "%.2f")) update_clipping_plane(true); @@ -991,6 +991,10 @@ void GLGizmoSlaSupports::on_set_state() if (m_state == On && m_old_state != On) { // the gizmo was just turned on Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on"))); + m_c->unstash_clipping_plane(); + update_clipping_plane(m_c->m_clipping_plane_distance != 0.f); + + // we'll now reload support points: if (m_c->m_model_object) reload_cache(); @@ -1026,8 +1030,9 @@ void GLGizmoSlaSupports::on_set_state() Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned off"))); m_parent.toggle_model_objects_visibility(true); m_normal_cache.clear(); - m_clipping_plane_distance = 0.f; - update_clipping_plane(); + m_c->stash_clipping_plane(); + m_c->m_clipping_plane_distance = 0.f; + update_clipping_plane(true); // Release clippers and the AABB raycaster. m_its = nullptr; m_c->m_object_clipper.reset(); @@ -1072,8 +1077,8 @@ void GLGizmoSlaSupports::on_stop_dragging() void GLGizmoSlaSupports::on_load(cereal::BinaryInputArchive& ar) { - ar(m_clipping_plane_distance, - *m_clipping_plane, + ar(m_c->m_clipping_plane_distance, + *m_c->m_clipping_plane, m_c->m_model_object_id, m_new_point_head_diameter, m_normal_cache, @@ -1086,8 +1091,8 @@ void GLGizmoSlaSupports::on_load(cereal::BinaryInputArchive& ar) void GLGizmoSlaSupports::on_save(cereal::BinaryOutputArchive& ar) const { - ar(m_clipping_plane_distance, - *m_clipping_plane, + ar(m_c->m_clipping_plane_distance, + *m_c->m_clipping_plane, m_c->m_model_object_id, m_new_point_head_diameter, m_normal_cache, @@ -1286,12 +1291,12 @@ bool GLGizmoSlaSupports::unsaved_changes() const void GLGizmoSlaSupports::update_clipping_plane(bool keep_normal) const { - Vec3d normal = (keep_normal && m_clipping_plane->get_normal() != Vec3d::Zero() ? - m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward()); + Vec3d normal = (keep_normal && m_c->m_clipping_plane->get_normal() != Vec3d::Zero() ? + m_c->m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward()); const Vec3d& center = m_c->m_model_object->instances[m_c->m_active_instance]->get_offset() + Vec3d(0., 0., m_z_shift); float dist = normal.dot(center); - *m_clipping_plane = ClippingPlane(normal, (dist - (-m_c->m_active_instance_bb_radius) - m_clipping_plane_distance * 2*m_c->m_active_instance_bb_radius)); + *m_c->m_clipping_plane = ClippingPlane(normal, (dist - (-m_c->m_active_instance_bb_radius) - m_c->m_clipping_plane_distance * 2*m_c->m_active_instance_bb_radius)); m_parent.set_as_dirty(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp index 152979f83..7ded6aadb 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSlaSupports.hpp @@ -103,8 +103,7 @@ private: mutable std::vector m_editing_cache; // a support point and whether it is currently selected std::vector m_normal_cache; // to restore after discarding changes or undo/redo - float m_clipping_plane_distance = 0.f; - std::unique_ptr m_clipping_plane; + //std::unique_ptr m_clipping_plane; // This map holds all translated description texts, so they can be easily referenced during layout calculations // etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect. From d407fda43326f4a767c85b6b7a4c900fe70a4e5b Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 3 Feb 2020 14:45:26 +0100 Subject: [PATCH 13/14] Hollowing gizmo - controls layout improvements --- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 30 +++++++++++++------------ 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 3db5e1e13..b585a8e4f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -40,7 +40,7 @@ bool GLGizmoHollow::on_init() { m_shortcut_key = WXK_CONTROL_H; m_desc["enable"] = _(L("Hollow this object")); - m_desc["preview"] = _(L("Preview")); + m_desc["preview"] = _(L("Preview hollowed and drilled model")); m_desc["offset"] = _(L("Offset")) + ": "; m_desc["quality"] = _(L("Quality")) + ": "; m_desc["closing_distance"] = _(L("Closing distance")) + ": "; @@ -661,18 +661,24 @@ RENDER_AGAIN: // First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that: const float settings_sliders_left = - std::max(std::max(m_imgui->calc_text_size(m_desc.at("offset")).x, - m_imgui->calc_text_size(m_desc.at("quality")).x), - m_imgui->calc_text_size(m_desc.at("closing_distance")).x) - + m_imgui->scaled(1.f); + std::max({m_imgui->calc_text_size(m_desc.at("offset")).x, + m_imgui->calc_text_size(m_desc.at("quality")).x, + m_imgui->calc_text_size(m_desc.at("closing_distance")).x, + m_imgui->calc_text_size(m_desc.at("hole_diameter")).x, + m_imgui->calc_text_size(m_desc.at("hole_depth")).x}) + + m_imgui->scaled(1.f); const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, m_imgui->calc_text_size(m_desc.at("reset_direction")).x) + m_imgui->scaled(1.5f); - const float diameter_slider_left = m_imgui->calc_text_size(m_desc.at("hole_diameter")).x + m_imgui->scaled(1.f); + const float diameter_slider_left = settings_sliders_left; //m_imgui->calc_text_size(m_desc.at("hole_diameter")).x + m_imgui->scaled(1.f); const float minimal_slider_width = m_imgui->scaled(4.f); - //const float buttons_width_approx = m_imgui->calc_text_size(m_desc.at("apply_changes")).x + m_imgui->calc_text_size(m_desc.at("discard_changes")).x + m_imgui->scaled(1.5f); - float window_width = minimal_slider_width + std::max(std::max(settings_sliders_left, clipping_slider_left), diameter_slider_left); - window_width = std::max(std::max(window_width, /*buttons_width_approx*/0.f), 0.f); + float window_width = minimal_slider_width + std::max({settings_sliders_left, clipping_slider_left, diameter_slider_left}); + window_width = std::max(window_width, m_imgui->calc_text_size(m_desc.at("preview")).x); + + if (m_imgui->button(m_desc["preview"])) + hollow_mesh(); + + ImGui::Separator(); { auto opts = get_config_options({"hollowing_enable"}); @@ -683,10 +689,6 @@ RENDER_AGAIN: } } - ImGui::SameLine(); - if (m_imgui->button(m_desc["preview"])) - hollow_mesh(); - m_imgui->disabled_begin(! m_enable_hollowing); std::vector opts_keys = {"hollowing_min_thickness", "hollowing_quality", "hollowing_closing_distance"}; @@ -911,7 +913,7 @@ bool GLGizmoHollow::on_is_selectable() const std::string GLGizmoHollow::on_get_name() const { - return (_(L("Hollowing")) + " [H]").ToUTF8().data(); + return (_(L("Hollowing and drilling")) + " [H]").ToUTF8().data(); } From 227cc4dc3378c1350618f12f2f1b61437666f92b Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 3 Feb 2020 15:42:54 +0100 Subject: [PATCH 14/14] Fixed conflicts after merge slaposHollowing was divided into slaposHollowing and slaposDrillHoles on master This commit takes this into account on the code that was merged from lm_drilling_backend_rebased --- src/libslic3r/SLAPrint.cpp | 6 +++--- src/libslic3r/SLAPrint.hpp | 2 +- src/libslic3r/SLAPrintSteps.cpp | 4 ++-- src/slic3r/GUI/GLCanvas3D.cpp | 10 ++++------ src/slic3r/GUI/Gizmos/GLGizmoBase.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 2 +- 6 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index e98e0edc4..06c4f687b 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -419,7 +419,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con if (model_object.sla_drain_holes != model_object_new.sla_drain_holes) { model_object.sla_drain_holes = model_object_new.sla_drain_holes; - update_apply_status(it_print_object_status->print_object->invalidate_step(slaposHollowing)); + update_apply_status(it_print_object_status->print_object->invalidate_step(slaposDrillHoles)); } // Copy the ModelObject name, input_file and instances. The instances will compared against PrintObject instances in the next step. @@ -1101,7 +1101,7 @@ const ExPolygons &SliceRecord::get_slice(SliceOrigin o) const bool SLAPrintObject::has_mesh(SLAPrintObjectStep step) const { switch (step) { - case slaposHollowing: + case slaposDrillHoles: return m_hollowing_data && !m_hollowing_data->hollow_mesh_with_holes.empty(); case slaposSupportTree: return ! this->support_mesh().empty(); @@ -1119,7 +1119,7 @@ TriangleMesh SLAPrintObject::get_mesh(SLAPrintObjectStep step) const return this->support_mesh(); case slaposPad: return this->pad_mesh(); - case slaposHollowing: + case slaposDrillHoles: if (m_hollowing_data) return m_hollowing_data->hollow_mesh_with_holes; [[fallthrough]]; diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index d2f121277..df052a9c7 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -78,7 +78,7 @@ public: // Support mesh is only valid if this->is_step_done(slaposPad) is true. const TriangleMesh& pad_mesh() const; - // Ready after this->is_step_done(slaposHollowing) is true + // Ready after this->is_step_done(slaposDrillHoles) is true const TriangleMesh& hollowed_interior_mesh() const; // Get the mesh that is going to be printed with all the modifications diff --git a/src/libslic3r/SLAPrintSteps.cpp b/src/libslic3r/SLAPrintSteps.cpp index 4bb6be7b0..4e19abd58 100644 --- a/src/libslic3r/SLAPrintSteps.cpp +++ b/src/libslic3r/SLAPrintSteps.cpp @@ -27,7 +27,7 @@ namespace { const std::array OBJ_STEP_LEVELS = { 10, // slaposHollowing, - 10, // slaposDrillHolesIfHollowed + 10, // slaposDrillHoles 10, // slaposObjectSlice, 20, // slaposSupportPoints, 10, // slaposSupportTree, @@ -39,7 +39,7 @@ std::string OBJ_STEP_LABELS(size_t idx) { switch (idx) { case slaposHollowing: return L("Hollowing model"); - case slaposDrillHoles: return L("Drilling holes into hollowed model."); + case slaposDrillHoles: return L("Drilling holes into model."); case slaposObjectSlice: return L("Slicing model"); case slaposSupportPoints: return L("Generating support points"); case slaposSupportTree: return L("Generating support tree"); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 1e90b85c5..3d0730198 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1978,7 +1978,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re // SLA steps to pull the preview meshes for. typedef std::array SLASteps; - SLASteps sla_steps = { slaposHollowing, slaposSupportTree, slaposPad }; + SLASteps sla_steps = { slaposDrillHoles, slaposSupportTree, slaposPad }; struct SLASupportState { std::array::value> step; }; @@ -2025,7 +2025,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re // Consider the DONE step without a valid mesh as invalid for the purpose // of mesh visualization. state.step[istep].state = PrintStateBase::INVALID; - else if (sla_steps[istep] != slaposHollowing) + else if (sla_steps[istep] != slaposDrillHoles) for (const ModelInstance* model_instance : print_object->model_object()->instances) // Only the instances, which are currently printable, will have the SLA support structures kept. // The instances outside the print bed will have the GLVolumes of their support structures released. @@ -2169,7 +2169,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re assert(it != model_object->instances.end()); int instance_idx = it - model_object->instances.begin(); for (size_t istep = 0; istep < sla_steps.size(); ++ istep) - if (sla_steps[istep] == slaposHollowing) { + if (sla_steps[istep] == slaposDrillHoles) { // Hollowing is a special case, where the mesh from the backend is being loaded into the 1st volume of an instance, // not into its own GLVolume. // There shall always be such a GLVolume allocated. @@ -2182,7 +2182,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re // The backend either produced a new hollowed mesh, or it invalidated the one that the front end has seen. volume.indexed_vertex_array.release_geometry(); if (state.step[istep].state == PrintStateBase::DONE) { - TriangleMesh mesh = print_object->get_mesh(slaposHollowing); + TriangleMesh mesh = print_object->get_mesh(slaposDrillHoles); assert(! mesh.empty()); mesh.transform(sla_print->sla_trafo(*m_model->objects[volume.object_idx()]).inverse()); volume.indexed_vertex_array.load_mesh(mesh); @@ -6106,8 +6106,6 @@ void GLCanvas3D::_load_sla_shells() unsigned int initial_volumes_count = (unsigned int)m_volumes.volumes.size(); for (const SLAPrintObject::Instance& instance : obj->instances()) { add_volume(*obj, 0, instance, obj->get_mesh_to_print(), GLVolume::MODEL_COLOR[0], true); -// if (! obj->hollowed_interior_mesh().empty()) -// add_volume(*obj, -int(slaposHollowing), instance, obj->hollowed_interior_mesh(), GLVolume::MODEL_COLOR[0], false); // Set the extruder_id and volume_id to achieve the same color as in the 3D scene when // through the update_volumes_colors_by_extruder() call. m_volumes.volumes.back()->extruder_id = obj->model_object()->volumes.front()->extruder_id(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp index 653bfefb5..af022352e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoBase.cpp @@ -354,7 +354,7 @@ bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas, ModelObject* mode // saved, a copy is stored as a member (FIXME) if (m_print_object_idx >=0) { const SLAPrintObject* po = canvas.sla_print()->objects()[m_print_object_idx]; - if (po->is_step_done(slaposHollowing)) { + if (po->is_step_done(slaposDrillHoles)) { m_backend_mesh_transformed = po->get_mesh_to_print(); m_backend_mesh_transformed.transform(canvas.sla_print()->sla_trafo(*m_model_object).inverse()); m_mesh = &m_backend_mesh_transformed; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 8afd98d11..57e0c787c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5130,7 +5130,7 @@ void Plater::reslice_SLA_supports(const ModelObject &object, bool postpone_error void Plater::reslice_SLA_hollowing(const ModelObject &object, bool postpone_error_messages) { - reslice_SLA_until_step(slaposHollowing, object, postpone_error_messages); + reslice_SLA_until_step(slaposDrillHoles, object, postpone_error_messages); } void Plater::reslice_SLA_until_step(SLAPrintObjectStep step, const ModelObject &object, bool postpone_error_messages)