From bea06e46a3d47a27c3fed548df83bece6a8d7d0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Fri, 4 Jun 2021 08:52:19 +0200 Subject: [PATCH 01/11] Show info about multi-material segmentation in ObjectList. --- src/slic3r/GUI/GUI_ObjectList.cpp | 16 +++++++++------- src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 6 +++++- src/slic3r/GUI/ObjectDataViewModel.cpp | 7 ++++--- src/slic3r/GUI/ObjectDataViewModel.hpp | 1 + 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index 53fbc4c1cbb..bd0e4923bdd 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2201,9 +2201,9 @@ void ObjectList::part_selection_changed() if (type == itInfo) { InfoItemType info_type = m_objects_model->GetInfoItemType(item); if (info_type != InfoItemType::VariableLayerHeight) { - GLGizmosManager::EType gizmo_type = - info_type == InfoItemType::CustomSupports ? GLGizmosManager::EType::FdmSupports - : GLGizmosManager::EType::Seam; + GLGizmosManager::EType gizmo_type = info_type == InfoItemType::CustomSupports ? GLGizmosManager::EType::FdmSupports : + info_type == InfoItemType::CustomSeam ? GLGizmosManager::EType::Seam : + GLGizmosManager::EType::MmuSegmentation; GLGizmosManager& gizmos_mgr = wxGetApp().plater()->canvas3D()->get_gizmos_manager(); if (gizmos_mgr.get_current_type() != gizmo_type) gizmos_mgr.open_gizmo(gizmo_type); @@ -2333,6 +2333,7 @@ void ObjectList::update_info_items(size_t obj_idx) for (InfoItemType type : {InfoItemType::CustomSupports, InfoItemType::CustomSeam, + InfoItemType::MmuSegmentation, InfoItemType::VariableLayerHeight}) { wxDataViewItem item = m_objects_model->GetInfoItemByType(item_obj, type); bool shows = item.IsOk(); @@ -2341,12 +2342,13 @@ void ObjectList::update_info_items(size_t obj_idx) switch (type) { case InfoItemType::CustomSupports : case InfoItemType::CustomSeam : + case InfoItemType::MmuSegmentation : should_show = printer_technology() == ptFFF && std::any_of(model_object->volumes.begin(), model_object->volumes.end(), - [type](const ModelVolume* mv) { - return ! (type == InfoItemType::CustomSupports - ? mv->supported_facets.empty() - : mv->seam_facets.empty()); + [type](const ModelVolume *mv) { + return !(type == InfoItemType::CustomSupports ? mv->supported_facets.empty() : + type == InfoItemType::CustomSeam ? mv->seam_facets.empty() : + mv->mmu_segmentation_facets.empty()); }); break; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index e04a5c49d25..3cf466dc382 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -7,6 +7,7 @@ #include "slic3r/GUI/Plater.hpp" #include "slic3r/GUI/BitmapCache.hpp" #include "slic3r/GUI/format.hpp" +#include "slic3r/GUI/GUI_ObjectList.hpp" #include "libslic3r/PresetBundle.hpp" #include "libslic3r/Model.hpp" @@ -375,8 +376,11 @@ void GLGizmoMmuSegmentation::update_model_object() const updated |= mv->mmu_segmentation_facets.set(*m_triangle_selectors[idx].get()); } - if (updated) + if (updated) { + const ModelObjectPtrs &mos = wxGetApp().model().objects; + wxGetApp().obj_list()->update_info_items(std::find(mos.begin(), mos.end(), mo) - mos.begin()); m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS)); + } } void GLGizmoMmuSegmentation::init_model_triangle_selectors() diff --git a/src/slic3r/GUI/ObjectDataViewModel.cpp b/src/slic3r/GUI/ObjectDataViewModel.cpp index f703ddcdbc8..482de650dfa 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.cpp +++ b/src/slic3r/GUI/ObjectDataViewModel.cpp @@ -62,9 +62,10 @@ ObjectDataViewModelNode::ObjectDataViewModelNode(ObjectDataViewModelNode* parent m_type(itInfo), m_extruder(wxEmptyString) { - m_name = info_type == InfoItemType::CustomSupports ? _L("Paint-on supports") - : info_type == InfoItemType::CustomSeam ? _L("Paint-on seam") - : _L("Variable layer height"); + m_name = info_type == InfoItemType::CustomSupports ? _L("Paint-on supports") : + info_type == InfoItemType::CustomSeam ? _L("Paint-on seam") : + info_type == InfoItemType::MmuSegmentation ? _L("Paint-on segmentation") : + _L("Variable layer height"); m_info_item_type = info_type; } diff --git a/src/slic3r/GUI/ObjectDataViewModel.hpp b/src/slic3r/GUI/ObjectDataViewModel.hpp index 11a9225caf6..a858b261970 100644 --- a/src/slic3r/GUI/ObjectDataViewModel.hpp +++ b/src/slic3r/GUI/ObjectDataViewModel.hpp @@ -50,6 +50,7 @@ enum class InfoItemType Undef, CustomSupports, CustomSeam, + MmuSegmentation, VariableLayerHeight }; From 1316e170539ac2abd862fdb8e43a08920d5bd318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Fri, 4 Jun 2021 12:31:04 +0200 Subject: [PATCH 02/11] Follow-up of 39fd8065a1dd0cc94b7396044392df6476592652: Apply changes also for MMU painting gizmo, so shader->start_using() is called only once. --- src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 3cf466dc382..ad726c110c0 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -462,16 +462,10 @@ void TriangleSelectorMmuGui::render(ImGuiWrapper *imgui) render_colors[color_idx] = m_iva_colors[color_idx].has_VBOs(); bool render_seed_fill = m_iva_seed_fill.has_VBOs(); - auto *shader = wxGetApp().get_shader("gouraud"); - if (!shader) return; - - shader->start_using(); - ScopeGuard guard([shader]() { - if (shader) - shader->stop_using(); - }); - shader->set_uniform("slope.actived", false); - shader->set_uniform("print_box.actived", false); + auto* shader = wxGetApp().get_current_shader(); + if (! shader) + return; + assert(shader->get_name() == "gouraud"); for (size_t color_idx = 0; color_idx < m_iva_colors.size(); ++color_idx) { if (render_colors[color_idx]) { From 7c58250e5bbdef8730475a16a454b2c9109cd07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Fri, 4 Jun 2021 12:54:00 +0200 Subject: [PATCH 03/11] Fixed cracks in MMU painting gizmo. All triangles, even not painted triangles, are now rendered inside MMU painting gizmo. The cracks were caused by using glPolygonOffset to resolve Z-fighting. All triangles of the object were firstly rendered entirely with a base color. And then paint triangles were drawn over these already rendered triangles. --- src/slic3r/GUI/GLCanvas3D.cpp | 5 ++- .../GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 38 +++++++++---------- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 2 +- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index daf8c599155..9662bacc0d3 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1168,10 +1168,11 @@ void GLCanvas3D::toggle_model_objects_visibility(bool visible, const ModelObject const GLGizmosManager& gm = get_gizmos_manager(); auto gizmo_type = gm.get_current_type(); if ( (gizmo_type == GLGizmosManager::FdmSupports - || gizmo_type == GLGizmosManager::Seam - || gizmo_type == GLGizmosManager::MmuSegmentation) + || gizmo_type == GLGizmosManager::Seam) && ! vol->is_modifier) vol->force_neutral_color = true; + else if (gizmo_type == GLGizmosManager::MmuSegmentation) + vol->is_active = false; else vol->force_native_color = true; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index ad726c110c0..0b6d7660bff 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -99,7 +99,7 @@ void GLGizmoMmuSegmentation::render_painter_gizmo() const glsafe(::glEnable(GL_BLEND)); glsafe(::glEnable(GL_DEPTH_TEST)); - render_triangles(selection); + render_triangles(selection, false); m_c->object_clipper()->render_cut(); render_cursor(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 64b41e46e91..dfb87880fe1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -13,8 +13,7 @@ -namespace Slic3r { -namespace GUI { +namespace Slic3r::GUI { GLGizmoPainterBase::GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) @@ -110,13 +109,15 @@ void GLGizmoPainterBase::set_painter_gizmo_data(const Selection& selection) -void GLGizmoPainterBase::render_triangles(const Selection& selection) const +void GLGizmoPainterBase::render_triangles(const Selection& selection, const bool use_polygon_offset_fill) const { const ModelObject* mo = m_c->selection_info()->model_object(); - glsafe(::glEnable(GL_POLYGON_OFFSET_FILL)); - ScopeGuard offset_fill_guard([]() { glsafe(::glDisable(GL_POLYGON_OFFSET_FILL)); } ); - glsafe(::glPolygonOffset(-5.0, -5.0)); + if (use_polygon_offset_fill) { + glsafe(::glEnable(GL_POLYGON_OFFSET_FILL)); + ScopeGuard offset_fill_guard([]() { glsafe(::glDisable(GL_POLYGON_OFFSET_FILL)); }); + glsafe(::glPolygonOffset(-5.0, -5.0)); + } // Take care of the clipping plane. The normal of the clipping plane is // saved with opposite sign than we need to pass to OpenGL (FIXME) @@ -578,8 +579,8 @@ void GLGizmoPainterBase::on_load(cereal::BinaryInputArchive&) void TriangleSelectorGUI::render(ImGuiWrapper* imgui) { - int enf_cnt = 0; - int blc_cnt = 0; + int enf_cnt = 0; + int blc_cnt = 0; int seed_fill_cnt = 0; m_iva_enforcers.release_geometry(); @@ -590,12 +591,8 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui) if (!tr.valid() || tr.is_split() || tr.get_state() == EnforcerBlockerType::NONE || tr.is_selected_by_seed_fill()) continue; - GLIndexedVertexArray& va = tr.get_state() == EnforcerBlockerType::ENFORCER - ? m_iva_enforcers - : m_iva_blockers; - int& cnt = tr.get_state() == EnforcerBlockerType::ENFORCER - ? enf_cnt - : blc_cnt; + GLIndexedVertexArray &va = tr.get_state() == EnforcerBlockerType::ENFORCER ? m_iva_enforcers : m_iva_blockers; + int &cnt = tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt : blc_cnt; for (int i=0; i<3; ++i) va.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal); @@ -617,8 +614,8 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui) m_iva_blockers.finalize_geometry(true); m_iva_seed_fill.finalize_geometry(true); - bool render_enf = m_iva_enforcers.has_VBOs(); - bool render_blc = m_iva_blockers.has_VBOs(); + bool render_enf = m_iva_enforcers.has_VBOs(); + bool render_blc = m_iva_blockers.has_VBOs(); bool render_seed_fill = m_iva_seed_fill.has_VBOs(); auto* shader = wxGetApp().get_current_shader(); @@ -627,19 +624,19 @@ void TriangleSelectorGUI::render(ImGuiWrapper* imgui) assert(shader->get_name() == "gouraud"); if (render_enf) { - std::array color = { 0.47f, 0.47f, 1.f, 1.f }; + std::array color = {0.47f, 0.47f, 1.f, 1.f}; shader->set_uniform("uniform_color", color); m_iva_enforcers.render(); } if (render_blc) { - std::array color = { 1.f, 0.44f, 0.44f, 1.f }; + std::array color = {1.f, 0.44f, 0.44f, 1.f}; shader->set_uniform("uniform_color", color); m_iva_blockers.render(); } if (render_seed_fill) { - std::array color = { 0.f, 1.00f, 0.44f, 1.f }; + std::array color = {0.f, 1.00f, 0.44f, 1.f}; shader->set_uniform("uniform_color", color); m_iva_seed_fill.render(); } @@ -746,5 +743,4 @@ void TriangleSelectorGUI::render_debug(ImGuiWrapper* imgui) -} // namespace GUI -} // namespace Slic3r +} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 8e2d05ea832..6622f7326dc 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -75,7 +75,7 @@ public: virtual void render_painter_gizmo() const = 0; protected: - void render_triangles(const Selection& selection) const; + void render_triangles(const Selection& selection, const bool use_polygon_offset_fill = true) const; void render_cursor() const; void render_cursor_circle() const; void render_cursor_sphere(const Transform3d& trafo) const; From 8079bf0139b2a44e400e1dc6788a2cf7c1d64e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 9 Jun 2021 08:02:06 +0200 Subject: [PATCH 04/11] Fixed a possible crash when closing the MMU painting gizmo cause by a non-virtual destructor. --- src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp | 2 ++ src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index 82b858d421f..0d28da25264 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -11,6 +11,7 @@ public: : TriangleSelectorGUI(mesh), m_colors(colors) { m_iva_colors = std::vector(colors.size()); } + ~TriangleSelectorMmuGui() override = default; // Render current selection. Transformation matrices are supposed // to be already set. @@ -26,6 +27,7 @@ class GLGizmoMmuSegmentation : public GLGizmoPainterBase public: GLGizmoMmuSegmentation(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) : GLGizmoPainterBase(parent, icon_filename, sprite_id) {} + ~GLGizmoMmuSegmentation() override = default; void render_painter_gizmo() const override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 6622f7326dc..88790dde5b3 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -31,6 +31,7 @@ class TriangleSelectorGUI : public TriangleSelector { public: explicit TriangleSelectorGUI(const TriangleMesh& mesh) : TriangleSelector(mesh) {} + virtual ~TriangleSelectorGUI() = default; // Render current selection. Transformation matrices are supposed // to be already set. @@ -64,7 +65,7 @@ private: public: GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); - ~GLGizmoPainterBase() override {} + ~GLGizmoPainterBase() override = default; virtual void set_painter_gizmo_data(const Selection& selection); virtual bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down); From ce2c69676c92274cf19c8218e278fde63c1ca247 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 9 Jun 2021 08:07:15 +0200 Subject: [PATCH 05/11] Modified MMU painting gizmo behavior so that all triangles aren't painted by default by the first extruder, which was causing several problems. This commit also fixed the following issues: 1) After loading a 3MF with painted triangles using the MMU painting gizmo, the painted triangles might not be displayed correctly in the MMU painting gizmo. 2) The MMU segmentation was unnecessarily executed for all layers and not just for the painted layers. 3) Object's base color wasn't changed when the assigned extruder for that object was changed while the MMU paint gizmo was opened. 4) Changing the base color of an object was only possible by removing all painted triangles. --- src/libslic3r/TriangleSelector.cpp | 28 +++++++-------- src/libslic3r/TriangleSelector.hpp | 4 +-- .../GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 34 ++++++++++++++----- .../GUI/Gizmos/GLGizmoMmuSegmentation.hpp | 15 ++++---- 4 files changed, 51 insertions(+), 30 deletions(-) diff --git a/src/libslic3r/TriangleSelector.cpp b/src/libslic3r/TriangleSelector.cpp index 976e3539130..52085b1785a 100644 --- a/src/libslic3r/TriangleSelector.cpp +++ b/src/libslic3r/TriangleSelector.cpp @@ -12,7 +12,7 @@ namespace Slic3r { #ifndef _NDEBUG bool TriangleSelector::verify_triangle_midpoints(const Triangle &tr) const { - for (int i = 0; i < 3; ++ i) { + for (int i = 0; i < 3; ++ i) { int v1 = tr.verts_idxs[i]; int v2 = tr.verts_idxs[next_idx_modulo(i, 3)]; int vmid = this->triangle_midpoint(tr, v1, v2); @@ -168,7 +168,7 @@ bool TriangleSelector::select_triangle(int facet_idx, EnforcerBlockerType type, for (int i = 0; i < 3; ++ i) neighbors(i) = neighbors_src.neighbor[i]; assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors)); - + if (! select_triangle_recursive(facet_idx, neighbors, type, triangle_splitting)) return false; @@ -249,11 +249,11 @@ int TriangleSelector::triangle_midpoint(const Triangle &tr, int vertexi, int ver assert(tr.verts_idxs[next_idx_modulo(edge, 3)] == vertexj); if (tr.number_of_split_sides() == 1) { - return edge == next_idx_modulo(tr.special_side(), 3) ? + return edge == next_idx_modulo(tr.special_side(), 3) ? m_triangles[tr.children[0]].verts_idxs[2] : this->triangle_midpoint(m_triangles[tr.children[edge == tr.special_side() ? 0 : 1]], vertexi, vertexj); } else if (tr.number_of_split_sides() == 2) { - return edge == next_idx_modulo(tr.special_side(), 3) ? + return edge == next_idx_modulo(tr.special_side(), 3) ? this->triangle_midpoint(m_triangles[tr.children[2]], vertexi, vertexj) : edge == tr.special_side() ? m_triangles[tr.children[0]].verts_idxs[1] : @@ -261,7 +261,7 @@ int TriangleSelector::triangle_midpoint(const Triangle &tr, int vertexi, int ver } else { assert(tr.number_of_split_sides() == 3); assert(tr.special_side() == 0); - return + return (edge == 0) ? m_triangles[tr.children[0]].verts_idxs[1] : (edge == 1) ? m_triangles[tr.children[1]].verts_idxs[2] : m_triangles[tr.children[2]].verts_idxs[2]; @@ -282,7 +282,7 @@ int TriangleSelector::triangle_midpoint_or_allocate(int itriangle, int vertexi, Vec3f c = 0.5f * (m_vertices[vertexi].v + m_vertices[vertexj].v); #ifdef EXPENSIVE_DEBUG_CHECKS // Verify that the vertex is really a new one. - auto it = std::find_if(m_vertices.begin(), m_vertices.end(), [this, c](const Vertex &v) { + auto it = std::find_if(m_vertices.begin(), m_vertices.end(), [this, c](const Vertex &v) { return v.ref_cnt > 0 && (v.v - c).norm() < EPSILON; }); assert(it == m_vertices.end()); #endif // EXPENSIVE_DEBUG_CHECKS @@ -736,7 +736,7 @@ TriangleSelector::TriangleSelector(const TriangleMesh& mesh) } -void TriangleSelector::reset(const EnforcerBlockerType reset_state) +void TriangleSelector::reset() { m_vertices.clear(); m_triangles.clear(); @@ -749,10 +749,10 @@ void TriangleSelector::reset(const EnforcerBlockerType reset_state) m_triangles.reserve(m_mesh->its.indices.size()); for (size_t i=0; iits.indices.size(); ++i) { const stl_triangle_vertex_indices& ind = m_mesh->its.indices[i]; - push_triangle(ind[0], ind[1], ind[2], i, reset_state); + push_triangle(ind[0], ind[1], ind[2], i); } m_orig_size_vertices = m_vertices.size(); - m_orig_size_indices = m_triangles.size(); + m_orig_size_indices = m_triangles.size(); } @@ -930,8 +930,8 @@ std::pair>, std::vector> TriangleSelector: // In case this is leaf, we better save information about its state. int n = int(tr.get_state()); if (n >= 3) { - assert(n <= 15); - if (n <= 15) { + assert(n <= 16); + if (n <= 16) { // Store "11" plus 4 bits of (n-3). data.second.insert(data.second.end(), { true, true }); n -= 3; @@ -963,9 +963,9 @@ std::pair>, std::vector> TriangleSelector: return out.data; } -void TriangleSelector::deserialize(const std::pair>, std::vector> &data, const EnforcerBlockerType init_state) +void TriangleSelector::deserialize(const std::pair>, std::vector> &data) { - reset(init_state); // dump any current state + reset(); // dump any current state // Vector to store all parents that have offsprings. struct ProcessingInfo { @@ -1058,7 +1058,7 @@ void TriangleSelector::deserialize(const std::pair>, std::vector> serialize() const; // Load serialized data. Assumes that correct mesh is loaded. - void deserialize(const std::pair>, std::vector> &data, const EnforcerBlockerType init_state = EnforcerBlockerType{0}); + void deserialize(const std::pair>, std::vector> &data); // For all triangles, remove the flag indicating that the triangle was selected by seed fill. void seed_fill_unselect_all_triangles(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 0b6d7660bff..e3af1146826 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -58,6 +58,20 @@ static std::vector get_extruders_names() return extruders_out; } +static std::vector get_extruder_id_for_volumes(const ModelObject &model_object) +{ + std::vector extruders_idx; + extruders_idx.reserve(model_object.volumes.size()); + for (const ModelVolume *model_volume : model_object.volumes) { + if (!model_volume->is_model_part()) + continue; + + extruders_idx.emplace_back(model_volume->extruder_id()); + } + + return extruders_idx; +} + void GLGizmoMmuSegmentation::init_extruders_data() { m_original_extruders_names = get_extruders_names(); @@ -114,12 +128,15 @@ void GLGizmoMmuSegmentation::set_painter_gizmo_data(const Selection &selection) if (m_state != On) return; - int prev_extruders_count = int(m_original_extruders_colors.size()); + ModelObject *model_object = m_c->selection_info()->model_object(); + int prev_extruders_count = int(m_original_extruders_colors.size()); if (prev_extruders_count != wxGetApp().extruders_edited_cnt() || get_extruders_colors() != m_original_extruders_colors) { this->init_extruders_data(); // Reinitialize triangle selectors because of change of extruder count need also change the size of GLIndexedVertexArray if (prev_extruders_count != wxGetApp().extruders_edited_cnt()) this->init_model_triangle_selectors(); + } else if (model_object != nullptr && get_extruder_id_for_volumes(*model_object) != m_original_volumes_extruder_idxs) { + this->init_model_triangle_selectors(); } } @@ -280,8 +297,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott for (ModelVolume *mv : mo->volumes) { if (mv->is_model_part()) { ++idx; - size_t extruder_id = (mv->extruder_id() > 0) ? mv->extruder_id() - 1 : 0; - m_triangle_selectors[idx]->reset(EnforcerBlockerType(extruder_id)); + m_triangle_selectors[idx]->reset(); } } @@ -395,10 +411,11 @@ void GLGizmoMmuSegmentation::init_model_triangle_selectors() // This mesh does not account for the possible Z up SLA offset. const TriangleMesh *mesh = &mv->mesh(); - size_t extruder_id = (mv->extruder_id() > 0) ? mv->extruder_id() - 1 : 0; - m_triangle_selectors.emplace_back(std::make_unique(*mesh, m_modified_extruders_colors)); - m_triangle_selectors.back()->deserialize(mv->mmu_segmentation_facets.get_data(), EnforcerBlockerType(extruder_id)); + int extruder_idx = (mv->extruder_id() > 0) ? mv->extruder_id() - 1 : 0; + m_triangle_selectors.emplace_back(std::make_unique(*mesh, m_modified_extruders_colors, m_original_extruders_colors[size_t(extruder_idx)])); + m_triangle_selectors.back()->deserialize(mv->mmu_segmentation_facets.get_data()); } + m_original_volumes_extruder_idxs = get_extruder_id_for_volumes(*mo); } void GLGizmoMmuSegmentation::update_from_model_object() @@ -468,9 +485,10 @@ void TriangleSelectorMmuGui::render(ImGuiWrapper *imgui) assert(shader->get_name() == "gouraud"); for (size_t color_idx = 0; color_idx < m_iva_colors.size(); ++color_idx) { + const std::array &color_source = (color_idx == 0) ? m_default_volume_color : m_colors[color_idx - 1]; if (render_colors[color_idx]) { - std::array color = {float(m_colors[color_idx][0]) / 255.0f, float(m_colors[color_idx][1]) / 255.0f, - float(m_colors[color_idx][2]) / 255.0f, 1.f}; + std::array color = {float(color_source[0]) / 255.0f, float(color_source[1]) / 255.0f, + float(color_source[2]) / 255.0f, 1.f}; shader->set_uniform("uniform_color", color); m_iva_colors[color_idx].render(); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index 0d28da25264..811e4cd2809 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -7,9 +7,10 @@ namespace Slic3r::GUI { class TriangleSelectorMmuGui : public TriangleSelectorGUI { public: - explicit TriangleSelectorMmuGui(const TriangleMesh& mesh, const std::vector> &colors) - : TriangleSelectorGUI(mesh), m_colors(colors) { - m_iva_colors = std::vector(colors.size()); + explicit TriangleSelectorMmuGui(const TriangleMesh& mesh, const std::vector> &colors, const std::array &default_volume_color) + : TriangleSelectorGUI(mesh), m_colors(colors), m_default_volume_color(default_volume_color) { + // Plus 1 is because the first position is allocated for non-painted triangles. + m_iva_colors = std::vector(colors.size() + 1); } ~TriangleSelectorMmuGui() override = default; @@ -19,7 +20,8 @@ public: private: const std::vector> &m_colors; - std::vector m_iva_colors; + std::vector m_iva_colors; + const std::array m_default_volume_color; }; class GLGizmoMmuSegmentation : public GLGizmoPainterBase @@ -37,8 +39,8 @@ protected: std::array get_cursor_sphere_left_button_color() const override; std::array get_cursor_sphere_right_button_color() const override; - EnforcerBlockerType get_left_button_state_type() const override { return EnforcerBlockerType(m_first_selected_extruder_idx); } - EnforcerBlockerType get_right_button_state_type() const override { return EnforcerBlockerType(m_second_selected_extruder_idx); } + EnforcerBlockerType get_left_button_state_type() const override { return EnforcerBlockerType(m_first_selected_extruder_idx + 1); } + EnforcerBlockerType get_right_button_state_type() const override { return EnforcerBlockerType(m_second_selected_extruder_idx + 1); } void on_render_input_window(float x, float y, float bottom_limit) override; std::string on_get_name() const override; @@ -52,6 +54,7 @@ protected: std::vector m_original_extruders_names; std::vector> m_original_extruders_colors; std::vector> m_modified_extruders_colors; + std::vector m_original_volumes_extruder_idxs; private: bool on_init() override; From 8fbd9f40e7094d2c61a27a73f6756165e5c4bd1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 9 Jun 2021 15:33:05 +0200 Subject: [PATCH 06/11] Refactoring and cleanup of painting gizmos. --- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 10 +- .../GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 108 ++++++++---------- .../GUI/Gizmos/GLGizmoMmuSegmentation.hpp | 21 ++-- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 91 +++++---------- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 14 +-- src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp | 10 +- 6 files changed, 107 insertions(+), 147 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 8c903470dde..3274f000c6c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -103,10 +103,10 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l const float buttons_width = std::max(button_enforce_width, button_cancel_width) + m_imgui->scaled(0.5f); const float minimal_slider_width = m_imgui->scaled(4.f); - float caption_max = 0.f; - float total_text_max = 0.; - for (const std::string& t : {"enforce", "block", "remove"}) { - caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t+"_caption")).x); + float caption_max = 0.f; + float total_text_max = 0.f; + for (const auto &t : std::array{"enforce", "block", "remove"}) { + caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t + "_caption")).x); total_text_max = std::max(total_text_max, caption_max + m_imgui->calc_text_size(m_desc.at(t)).x); } caption_max += m_imgui->scaled(1.f); @@ -124,7 +124,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l m_imgui->text(text); }; - for (const std::string& t : {"enforce", "block", "remove"}) + for (const auto &t : std::array{"enforce", "block", "remove"}) draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t)); m_imgui->text(""); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index e3af1146826..50d74e04702 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -33,15 +33,15 @@ bool GLGizmoMmuSegmentation::on_is_selectable() const && wxGetApp().get_mode() != comSimple && wxGetApp().extruders_edited_cnt() > 1); } -static std::vector> get_extruders_colors() +static std::vector> get_extruders_colors() { - unsigned char rgb_color[3] = {}; - std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); - std::vector> colors_out(colors.size()); + unsigned char rgb_color[3] = {}; + std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); + std::vector> colors_out(colors.size()); for (const std::string &color : colors) { Slic3r::GUI::BitmapCache::parse_color(color, rgb_color); size_t color_idx = &color - &colors.front(); - colors_out[color_idx] = {rgb_color[0], rgb_color[1], rgb_color[2]}; + colors_out[color_idx] = {float(rgb_color[0]) / 255.f, float(rgb_color[1]) / 255.f, float(rgb_color[2]) / 255.f, 1.f}; } return colors_out; @@ -140,16 +140,19 @@ void GLGizmoMmuSegmentation::set_painter_gizmo_data(const Selection &selection) } } -static void render_extruders_combo(const std::string &label, - const std::vector &extruders, - const std::vector> &extruders_colors, - size_t &selection_idx) +static void render_extruders_combo(const std::string &label, + const std::vector &extruders, + const std::vector> &extruders_colors, + size_t &selection_idx) { assert(!extruders_colors.empty()); assert(extruders_colors.size() == extruders_colors.size()); - size_t selection_out = selection_idx; + auto convert_to_imu32 = [](const std::array &color) -> ImU32 { + return IM_COL32(uint8_t(color[0] * 255.f), uint8_t(color[1] * 255.f), uint8_t(color[2] * 255.f), uint8_t(color[3] * 255.f)); + }; + size_t selection_out = selection_idx; // It is necessary to use BeginGroup(). Otherwise, when using SameLine() is called, then other items will be drawn inside the combobox. ImGui::BeginGroup(); ImVec2 combo_pos = ImGui::GetCursorScreenPos(); @@ -164,8 +167,7 @@ static void render_extruders_combo(const std::string &la ImGui::SameLine(); ImGuiStyle &style = ImGui::GetStyle(); float height = ImGui::GetTextLineHeight(); - ImGui::GetWindowDrawList()->AddRectFilled(start_position, ImVec2(start_position.x + height + height / 2, start_position.y + height), - IM_COL32(extruders_colors[extruder_idx][0], extruders_colors[extruder_idx][1], extruders_colors[extruder_idx][2], 255)); + ImGui::GetWindowDrawList()->AddRectFilled(start_position, ImVec2(start_position.x + height + height / 2, start_position.y + height), convert_to_imu32(extruders_colors[extruder_idx])); ImGui::GetWindowDrawList()->AddRect(start_position, ImVec2(start_position.x + height + height / 2, start_position.y + height), IM_COL32_BLACK); ImGui::SetCursorScreenPos(ImVec2(start_position.x + height + height / 2 + style.FramePadding.x, start_position.y)); @@ -183,9 +185,7 @@ static void render_extruders_combo(const std::string &la ImVec2 p = ImGui::GetCursorScreenPos(); float height = ImGui::GetTextLineHeight(); - ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + height + height / 2, p.y + height), - IM_COL32(extruders_colors[selection_idx][0], extruders_colors[selection_idx][1], - extruders_colors[selection_idx][2], 255)); + ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + height + height / 2, p.y + height), convert_to_imu32(extruders_colors[selection_idx])); ImGui::GetWindowDrawList()->AddRect(p, ImVec2(p.x + height + height / 2, p.y + height), IM_COL32_BLACK); ImGui::SetCursorScreenPos(ImVec2(p.x + height + height / 2 + style.FramePadding.x, p.y)); @@ -224,7 +224,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott float caption_max = 0.f; float total_text_max = 0.; - for (const std::string &t : {"first_color", "second_color", "remove"}) { + for (const auto &t : std::array{"first_color", "second_color", "remove"}) { caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t + "_caption")).x); total_text_max = std::max(total_text_max, caption_max + m_imgui->calc_text_size(m_desc.at(t)).x); } @@ -243,33 +243,33 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott m_imgui->text(text); }; - for (const std::string &t : {"first_color", "second_color", "remove"}) + for (const auto &t : std::array{"first_color", "second_color", "remove"}) draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t)); m_imgui->text(""); ImGui::Separator(); - const std::array &select_first_color = m_modified_extruders_colors[m_first_selected_extruder_idx]; - const std::array &select_second_color = m_modified_extruders_colors[m_second_selected_extruder_idx]; - m_imgui->text(m_desc.at("first_color")); ImGui::SameLine(combo_label_width); ImGui::PushItemWidth(window_width - combo_label_width - color_button_width); render_extruders_combo("##first_color_combo", m_original_extruders_names, m_original_extruders_colors, m_first_selected_extruder_idx); ImGui::SameLine(); - ImVec4 first_color = ImVec4(float(select_first_color[0]) / 255.0f, float(select_first_color[1]) / 255.0f, float(select_first_color[2]) / 255.0f, 1.0f); - ImVec4 second_color = ImVec4(float(select_second_color[0]) / 255.0f, float(select_second_color[1]) / 255.0f, float(select_second_color[2]) / 255.0f, 1.0f); + const std::array &select_first_color = m_modified_extruders_colors[m_first_selected_extruder_idx]; + ImVec4 first_color = ImVec4(select_first_color[0], select_first_color[1], select_first_color[2], select_first_color[3]); if(ImGui::ColorEdit4("First color##color_picker", (float*)&first_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) - m_modified_extruders_colors[m_first_selected_extruder_idx] = {uint8_t(first_color.x * 255.0f), uint8_t(first_color.y * 255.0f), uint8_t(first_color.z * 255.0f)}; + m_modified_extruders_colors[m_first_selected_extruder_idx] = {first_color.x, first_color.y, first_color.z, first_color.w}; m_imgui->text(m_desc.at("second_color")); ImGui::SameLine(combo_label_width); ImGui::PushItemWidth(window_width - combo_label_width - color_button_width); render_extruders_combo("##second_color_combo", m_original_extruders_names, m_original_extruders_colors, m_second_selected_extruder_idx); ImGui::SameLine(); + + const std::array &select_second_color = m_modified_extruders_colors[m_second_selected_extruder_idx]; + ImVec4 second_color = ImVec4(select_second_color[0], select_second_color[1], select_second_color[2], select_second_color[3]); if(ImGui::ColorEdit4("Second color##color_picker", (float*)&second_color, ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel)) - m_modified_extruders_colors[m_second_selected_extruder_idx] = {uint8_t(second_color.x * 255.0f), uint8_t(second_color.y * 255.0f), uint8_t(second_color.z * 255.0f)}; + m_modified_extruders_colors[m_second_selected_extruder_idx] = {second_color.x, second_color.y, second_color.z, second_color.w}; ImGui::Separator(); @@ -431,74 +431,66 @@ PainterGizmoType GLGizmoMmuSegmentation::get_painter_type() const std::array GLGizmoMmuSegmentation::get_cursor_sphere_left_button_color() const { - const std::array &color = m_modified_extruders_colors[m_first_selected_extruder_idx]; - return {float(color[0]) / 255.0f, float(color[1]) / 255.0f, float(color[2]) / 255.0f, 0.25f}; + const std::array &color = m_modified_extruders_colors[m_first_selected_extruder_idx]; + return {color[0], color[1], color[2], 0.25f}; } std::array GLGizmoMmuSegmentation::get_cursor_sphere_right_button_color() const { - const std::array &color = m_modified_extruders_colors[m_second_selected_extruder_idx]; - return {float(color[0]) / 255.0f, float(color[1]) / 255.0f, float(color[2]) / 255.0f, 0.25f}; + const std::array &color = m_modified_extruders_colors[m_second_selected_extruder_idx]; + return {color[0], color[1], color[2], 0.25f}; } void TriangleSelectorMmuGui::render(ImGuiWrapper *imgui) { + static constexpr std::array seed_fill_color{0.f, 1.f, 0.44f, 1.f}; + std::vector color_cnt(m_iva_colors.size()); int seed_fill_cnt = 0; for (auto &iva_color : m_iva_colors) iva_color.release_geometry(); m_iva_seed_fill.release_geometry(); + auto append_triangle = [this](GLIndexedVertexArray &iva, int &cnt, const Triangle &tr) -> void { + for (int i = 0; i < 3; ++i) + iva.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal); + iva.push_triangle(cnt, cnt + 1, cnt + 2); + cnt += 3; + }; + for (size_t color_idx = 0; color_idx < m_iva_colors.size(); ++color_idx) { for (const Triangle &tr : m_triangles) { if (!tr.valid() || tr.is_split() || tr.is_selected_by_seed_fill() || tr.get_state() != EnforcerBlockerType(color_idx)) continue; - - for (int i = 0; i < 3; ++i) - m_iva_colors[color_idx].push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal); - m_iva_colors[color_idx].push_triangle(color_cnt[color_idx], color_cnt[color_idx] + 1, color_cnt[color_idx] + 2); - color_cnt[color_idx] += 3; + append_triangle(m_iva_colors[color_idx], color_cnt[color_idx], tr); } } for (const Triangle &tr : m_triangles) { - if (!tr.valid() || tr.is_split() || !tr.is_selected_by_seed_fill()) continue; - - for (int i = 0; i < 3; ++i) - m_iva_seed_fill.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal); - m_iva_seed_fill.push_triangle(seed_fill_cnt, seed_fill_cnt + 1, seed_fill_cnt + 2); - seed_fill_cnt += 3; + if (!tr.valid() || tr.is_split() || !tr.is_selected_by_seed_fill()) + continue; + append_triangle(m_iva_seed_fill, seed_fill_cnt, tr); } for (auto &iva_color : m_iva_colors) iva_color.finalize_geometry(true); m_iva_seed_fill.finalize_geometry(true); - std::vector render_colors(m_iva_colors.size()); - for (size_t color_idx = 0; color_idx < m_iva_colors.size(); ++color_idx) - render_colors[color_idx] = m_iva_colors[color_idx].has_VBOs(); - bool render_seed_fill = m_iva_seed_fill.has_VBOs(); - - auto* shader = wxGetApp().get_current_shader(); - if (! shader) + auto *shader = wxGetApp().get_current_shader(); + if (!shader) return; assert(shader->get_name() == "gouraud"); - for (size_t color_idx = 0; color_idx < m_iva_colors.size(); ++color_idx) { - const std::array &color_source = (color_idx == 0) ? m_default_volume_color : m_colors[color_idx - 1]; - if (render_colors[color_idx]) { - std::array color = {float(color_source[0]) / 255.0f, float(color_source[1]) / 255.0f, - float(color_source[2]) / 255.0f, 1.f}; + auto render = [&shader](const GLIndexedVertexArray &iva, const std::array &color) -> void { + if (iva.has_VBOs()) { shader->set_uniform("uniform_color", color); - m_iva_colors[color_idx].render(); + iva.render(); } - } + }; - if (render_seed_fill) { - std::array color = {0.f, 1.f, 0.44f, 1.f}; - shader->set_uniform("uniform_color", color); - m_iva_seed_fill.render(); - } + for (size_t color_idx = 0; color_idx < m_iva_colors.size(); ++color_idx) + render(m_iva_colors[color_idx], (color_idx == 0) ? m_default_volume_color : m_colors[color_idx - 1]); + render(m_iva_seed_fill, seed_fill_color); } wxString GLGizmoMmuSegmentation::handle_snapshot_action_name(bool shift_down, GLGizmoPainterBase::Button button_down) const diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index 811e4cd2809..f5c97801bcf 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -7,7 +7,7 @@ namespace Slic3r::GUI { class TriangleSelectorMmuGui : public TriangleSelectorGUI { public: - explicit TriangleSelectorMmuGui(const TriangleMesh& mesh, const std::vector> &colors, const std::array &default_volume_color) + explicit TriangleSelectorMmuGui(const TriangleMesh& mesh, const std::vector> &colors, const std::array &default_volume_color) : TriangleSelectorGUI(mesh), m_colors(colors), m_default_volume_color(default_volume_color) { // Plus 1 is because the first position is allocated for non-painted triangles. m_iva_colors = std::vector(colors.size() + 1); @@ -19,9 +19,10 @@ public: void render(ImGuiWrapper* imgui) override; private: - const std::vector> &m_colors; - std::vector m_iva_colors; - const std::array m_default_volume_color; + const std::vector> &m_colors; + std::vector m_iva_colors; + const std::array m_default_volume_color; + GLIndexedVertexArray m_iva_seed_fill; }; class GLGizmoMmuSegmentation : public GLGizmoPainterBase @@ -49,12 +50,12 @@ protected: wxString handle_snapshot_action_name(bool shift_down, Button button_down) const override; - size_t m_first_selected_extruder_idx = 0; - size_t m_second_selected_extruder_idx = 1; - std::vector m_original_extruders_names; - std::vector> m_original_extruders_colors; - std::vector> m_modified_extruders_colors; - std::vector m_original_volumes_extruder_idxs; + size_t m_first_selected_extruder_idx = 0; + size_t m_second_selected_extruder_idx = 1; + std::vector m_original_extruders_names; + std::vector> m_original_extruders_colors; + std::vector> m_modified_extruders_colors; + std::vector m_original_volumes_extruder_idxs; private: bool on_init() override; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index dfb87880fe1..2c00e8f336c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -126,8 +126,8 @@ void GLGizmoPainterBase::render_triangles(const Selection& selection, const bool if (clipping_plane_active) { const ClippingPlane* clp = m_c->object_clipper()->get_clipping_plane(); for (size_t i=0; i<3; ++i) - clp_dataf[i] = -1. * clp->get_data()[i]; - clp_dataf[3] = clp->get_data()[3]; + clp_dataf[i] = -1.f * float(clp->get_data()[i]); + clp_dataf[3] = float(clp->get_data()[3]); } auto *shader = wxGetApp().get_shader("gouraud"); @@ -203,13 +203,13 @@ void GLGizmoPainterBase::render_cursor() const void GLGizmoPainterBase::render_cursor_circle() const { - const Camera& camera = wxGetApp().plater()->get_camera(); - float zoom = (float)camera.get_zoom(); - float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; + const Camera &camera = wxGetApp().plater()->get_camera(); + auto zoom = (float) camera.get_zoom(); + float inv_zoom = (zoom != 0.0f) ? 1.0f / zoom : 0.0f; - Size cnv_size = m_parent.get_canvas_size(); - float cnv_half_width = 0.5f * (float)cnv_size.get_width(); - float cnv_half_height = 0.5f * (float)cnv_size.get_height(); + Size cnv_size = m_parent.get_canvas_size(); + float cnv_half_width = 0.5f * (float) cnv_size.get_width(); + float cnv_half_height = 0.5f * (float) cnv_size.get_height(); if ((cnv_half_width == 0.0f) || (cnv_half_height == 0.0f)) return; Vec2d mouse_pos(m_parent.get_local_mouse_position()(0), m_parent.get_local_mouse_position()(1)); @@ -217,11 +217,8 @@ void GLGizmoPainterBase::render_cursor_circle() const center = center * inv_zoom; glsafe(::glLineWidth(1.5f)); - float color[3]; - color[0] = 0.f; - color[1] = 1.f; - color[2] = 0.3f; - glsafe(::glColor3fv(color)); + static const std::array color = {0.f, 1.f, 0.3f}; + glsafe(::glColor3fv(color.data())); glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glPushMatrix()); @@ -515,11 +512,7 @@ bool GLGizmoPainterBase::on_is_activable() const // Check that none of the selected volumes is outside. Only SLA auxiliaries (supports) are allowed outside. const Selection::IndicesList& list = selection.get_volume_idxs(); - for (const auto& idx : list) - if (selection.get_volume(idx)->is_outside) - return false; - - return true; + return std::all_of(list.cbegin(), list.cend(), [&selection](unsigned int idx) { return !selection.get_volume(idx)->is_outside; }); } bool GLGizmoPainterBase::on_is_selectable() const @@ -579,66 +572,42 @@ void GLGizmoPainterBase::on_load(cereal::BinaryInputArchive&) void TriangleSelectorGUI::render(ImGuiWrapper* imgui) { + static constexpr std::array enforcers_color{0.47f, 0.47f, 1.f, 1.f}; + static constexpr std::array blockers_color{1.f, 0.44f, 0.44f, 1.f}; + int enf_cnt = 0; int blc_cnt = 0; - int seed_fill_cnt = 0; - m_iva_enforcers.release_geometry(); - m_iva_blockers.release_geometry(); - m_iva_seed_fill.release_geometry(); + for (auto *iva : {&m_iva_enforcers, &m_iva_blockers}) + iva->release_geometry(); for (const Triangle& tr : m_triangles) { - if (!tr.valid() || tr.is_split() || tr.get_state() == EnforcerBlockerType::NONE || tr.is_selected_by_seed_fill()) + if (!tr.valid() || tr.is_split() || tr.get_state() == EnforcerBlockerType::NONE) continue; - GLIndexedVertexArray &va = tr.get_state() == EnforcerBlockerType::ENFORCER ? m_iva_enforcers : m_iva_blockers; - int &cnt = tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt : blc_cnt; + GLIndexedVertexArray &iva = tr.get_state() == EnforcerBlockerType::ENFORCER ? m_iva_enforcers : m_iva_blockers; + int & cnt = tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt : blc_cnt; - for (int i=0; i<3; ++i) - va.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal); - va.push_triangle(cnt, cnt + 1, cnt + 2); + for (int i = 0; i < 3; ++i) + iva.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal); + iva.push_triangle(cnt, cnt + 1, cnt + 2); cnt += 3; } - for (const Triangle &tr : m_triangles) { - if (!tr.valid() || tr.is_split() || !tr.is_selected_by_seed_fill()) - continue; - - for (int i = 0; i < 3; ++i) - m_iva_seed_fill.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal); - m_iva_seed_fill.push_triangle(seed_fill_cnt, seed_fill_cnt + 1, seed_fill_cnt + 2); - seed_fill_cnt += 3; - } - - m_iva_enforcers.finalize_geometry(true); - m_iva_blockers.finalize_geometry(true); - m_iva_seed_fill.finalize_geometry(true); - - bool render_enf = m_iva_enforcers.has_VBOs(); - bool render_blc = m_iva_blockers.has_VBOs(); - bool render_seed_fill = m_iva_seed_fill.has_VBOs(); + for (auto *iva : {&m_iva_enforcers, &m_iva_blockers}) + iva->finalize_geometry(true); auto* shader = wxGetApp().get_current_shader(); if (! shader) return; assert(shader->get_name() == "gouraud"); - if (render_enf) { - std::array color = {0.47f, 0.47f, 1.f, 1.f}; - shader->set_uniform("uniform_color", color); - m_iva_enforcers.render(); - } - - if (render_blc) { - std::array color = {1.f, 0.44f, 0.44f, 1.f}; - shader->set_uniform("uniform_color", color); - m_iva_blockers.render(); - } - - if (render_seed_fill) { - std::array color = {0.f, 1.00f, 0.44f, 1.f}; - shader->set_uniform("uniform_color", color); - m_iva_seed_fill.render(); + for (auto iva : {std::make_pair(&m_iva_enforcers, enforcers_color), + std::make_pair(&m_iva_blockers, blockers_color)}) { + if (iva.first->has_VBOs()) { + shader->set_uniform("uniform_color", iva.second); + iva.first->render(); + } } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 88790dde5b3..3bba3fde577 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -35,7 +35,8 @@ public: // Render current selection. Transformation matrices are supposed // to be already set. - virtual void render(ImGuiWrapper* imgui = nullptr); + virtual void render(ImGuiWrapper *imgui); + void render() { this->render(nullptr); } #ifdef PRUSASLICER_TRIANGLE_SELECTOR_DEBUG void render_debug(ImGuiWrapper* imgui); @@ -44,11 +45,9 @@ public: #endif private: - GLIndexedVertexArray m_iva_enforcers; - GLIndexedVertexArray m_iva_blockers; + GLIndexedVertexArray m_iva_enforcers; + GLIndexedVertexArray m_iva_blockers; std::array m_varrays; -protected: - GLIndexedVertexArray m_iva_seed_fill; }; @@ -60,8 +59,8 @@ class GLGizmoPainterBase : public GLGizmoBase private: ObjectID m_old_mo_id; size_t m_old_volumes_size = 0; - virtual void on_render() const override {} - virtual void on_render_for_picking() const override {} + void on_render() const override {} + void on_render_for_picking() const override {} public: GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); @@ -83,7 +82,6 @@ protected: virtual void update_model_object() const = 0; virtual void update_from_model_object() = 0; void activate_internal_undo_redo_stack(bool activate); - void set_cursor_type(TriangleSelector::CursorType); virtual std::array get_cursor_sphere_left_button_color() const { return {0.f, 0.f, 1.f, 0.25f}; } virtual std::array get_cursor_sphere_right_button_color() const { return {1.f, 0.f, 0.f, 0.25f}; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index 7a274c92708..d3c0c7d041f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -86,10 +86,10 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) const float button_width = m_imgui->calc_text_size(m_desc.at("remove_all")).x + m_imgui->scaled(1.f); const float minimal_slider_width = m_imgui->scaled(4.f); - float caption_max = 0.f; - float total_text_max = 0.; - for (const std::string& t : {"enforce", "block", "remove"}) { - caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t+"_caption")).x); + float caption_max = 0.f; + float total_text_max = 0.f; + for (const auto &t : std::array{"enforce", "block", "remove"}) { + caption_max = std::max(caption_max, m_imgui->calc_text_size(m_desc.at(t + "_caption")).x); total_text_max = std::max(total_text_max, caption_max + m_imgui->calc_text_size(m_desc.at(t)).x); } caption_max += m_imgui->scaled(1.f); @@ -107,7 +107,7 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) m_imgui->text(text); }; - for (const std::string& t : {"enforce", "block", "remove"}) + for (const auto &t : std::array{"enforce", "block", "remove"}) draw_text_with_caption(m_desc.at(t + "_caption"), m_desc.at(t)); m_imgui->text(""); From 0ce6e666cf3ea456420a7d580bf87ffb68189b03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 9 Jun 2021 16:44:35 +0200 Subject: [PATCH 07/11] Moved debug prints out of parallel cycles, and more debug prints were added for multi-material segmentation. --- src/libslic3r/MultiMaterialSegmentation.cpp | 32 +++++++++++++++------ 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index a4237880f4f..6f1ca61c0e1 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -525,7 +525,7 @@ struct MMU_Graph nodes[to_idx].remove_edge(from_idx); } - size_t get_global_index(const size_t poly_idx, const size_t point_idx) const { return polygon_idx_offset[poly_idx] + point_idx; } + [[nodiscard]] size_t get_global_index(const size_t poly_idx, const size_t point_idx) const { return polygon_idx_offset[poly_idx] + point_idx; } void append_edge(const size_t &from_idx, const size_t &to_idx, int color = -1, ARC_TYPE type = ARC_TYPE::NON_BORDER) { @@ -546,7 +546,7 @@ struct MMU_Graph // Ignoring arcs in the opposite direction MMU_Graph::Arc get_arc(size_t idx) { return this->arcs[idx * 2]; } - size_t nodes_count() const { return this->nodes.size(); } + [[nodiscard]] size_t nodes_count() const { return this->nodes.size(); } void remove_nodes_with_one_arc() { @@ -602,12 +602,12 @@ struct MMU_Graph return vertex->color() < this->all_border_points; } - inline bool is_edge_attach_to_contour(const voronoi_diagram::const_edge_iterator &edge_iterator) const + [[nodiscard]] inline bool is_edge_attach_to_contour(const voronoi_diagram::const_edge_iterator &edge_iterator) const { return this->is_vertex_on_contour(edge_iterator->vertex0()) || this->is_vertex_on_contour(edge_iterator->vertex1()); } - inline bool is_edge_connecting_two_contour_vertices(const voronoi_diagram::const_edge_iterator &edge_iterator) const + [[nodiscard]] inline bool is_edge_connecting_two_contour_vertices(const voronoi_diagram::const_edge_iterator &edge_iterator) const { return this->is_vertex_on_contour(edge_iterator->vertex0()) && this->is_vertex_on_contour(edge_iterator->vertex1()); } @@ -1130,6 +1130,7 @@ static void cut_segmented_layers(const std::vector const float cut_width, const std::function &throw_on_cancel_callback) { + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - cutting segmented layers in parallel - begin"; tbb::parallel_for(tbb::blocked_range(0, segmented_regions.size()),[&](const tbb::blocked_range& range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { throw_on_cancel_callback(); @@ -1143,6 +1144,7 @@ static void cut_segmented_layers(const std::vector segmented_regions[layer_idx] = segmented_regions_cuts; } }); // end of parallel_for + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - cutting segmented layers in parallel - end"; } // Returns MMU segmentation of top and bottom layers based on painting in MMU segmentation gizmo @@ -1154,6 +1156,8 @@ static inline std::vector> mmu_segmentation_top_and_bott const ConstLayerPtrsAdaptor layers = print_object.layers(); std::vector> triangles_by_color(num_extruders); triangles_by_color.assign(num_extruders, std::vector(layers.size())); + + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - top and bottom layers - projection of painted triangles - begin"; for (const ModelVolume *mv : print_object.model_object()->volumes) { for (size_t extruder_idx = 0; extruder_idx < num_extruders; ++extruder_idx) { throw_on_cancel_callback(); @@ -1203,6 +1207,7 @@ static inline std::vector> mmu_segmentation_top_and_bott } } } + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - top and bottom layers - projection of painted triangles - end"; auto get_extrusion_width = [&layers = std::as_const(layers)](const size_t layer_idx) -> float { auto extrusion_width_it = std::max_element(layers[layer_idx]->regions().begin(), layers[layer_idx]->regions().end(), @@ -1272,8 +1277,8 @@ static inline std::vector> mmu_segmentation_top_and_bott triangles_by_color_bottom.assign(num_extruders, std::vector(input_expolygons.size())); triangles_by_color_top.assign(num_extruders, std::vector(input_expolygons.size())); + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - segmentation of top layer - begin"; for (size_t layer_idx = 0; layer_idx < input_expolygons.size(); ++layer_idx) { - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation of top layer: " << layer_idx; float extrusion_width = scale_(get_extrusion_width(layer_idx)); int top_solid_layers = get_top_solid_layers(layer_idx); ExPolygons top_expolygon = top_layers[layer_idx]; @@ -1306,9 +1311,10 @@ static inline std::vector> mmu_segmentation_top_and_bott } } } + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - segmentation of top layer - end"; + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - segmentation of bottom layer - begin"; for (size_t layer_idx = 0; layer_idx < input_expolygons.size(); ++layer_idx) { - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation of bottom layer: " << layer_idx; float extrusion_width = scale_(get_extrusion_width(layer_idx)); int bottom_solid_layers = get_bottom_solid_layers(layer_idx); const ExPolygons &bottom_expolygon = bottom_layers[layer_idx]; @@ -1340,6 +1346,7 @@ static inline std::vector> mmu_segmentation_top_and_bott } } } + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - segmentation of bottom layer - end"; std::vector> triangles_by_color_merged(num_extruders); triangles_by_color_merged.assign(num_extruders, std::vector(input_expolygons.size())); @@ -1369,9 +1376,9 @@ static std::vector>> merge_segmented_la { std::vector>> segmented_regions_merged(segmented_regions.size()); + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - merging segmented layers in parallel - begin"; tbb::parallel_for(tbb::blocked_range(0, segmented_regions.size()), [&](const tbb::blocked_range &range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - merging region: " << layer_idx; for (const std::pair &colored_expoly : segmented_regions[layer_idx]) { throw_on_cancel_callback(); ExPolygons cut_colored_expoly = {colored_expoly.first}; @@ -1386,6 +1393,7 @@ static std::vector>> merge_segmented_la segmented_regions_merged[layer_idx].emplace_back(std::move(expoly), color_idx); } }); // end of parallel_for + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - merging segmented layers in parallel - end"; return segmented_regions_merged; } @@ -1402,6 +1410,7 @@ std::vector>> multi_material_segmentati throw_on_cancel_callback(); // Merge all regions and remove small holes + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - slices preparation in parallel - begin"; tbb::parallel_for(tbb::blocked_range(0, layers.size()), [&](const tbb::blocked_range &range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { throw_on_cancel_callback(); @@ -1425,6 +1434,7 @@ std::vector>> multi_material_segmentati input_polygons[layer_idx] = to_polygons(input_expolygons[layer_idx]); } }); // end of parallel_for + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - slices preparation in parallel - end"; for (size_t layer_idx = 0; layer_idx < layers.size(); ++layer_idx) { throw_on_cancel_callback(); @@ -1434,6 +1444,7 @@ std::vector>> multi_material_segmentati edge_grids[layer_idx].create(input_expolygons[layer_idx], coord_t(scale_(10.))); } + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - projection of painted triangles - begin"; for (const ModelVolume *mv : print_object.model_object()->volumes) { const size_t num_extruders = print_object.print()->config().nozzle_diameter.size(); for (size_t extruder_idx = 1; extruder_idx < num_extruders; ++extruder_idx) { @@ -1500,12 +1511,14 @@ std::vector>> multi_material_segmentati } } } + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - projection of painted triangles - end"; + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - painted layers count: " + << std::count_if(painted_lines.begin(), painted_lines.end(), [](const std::vector &pl) { return !pl.empty(); }); + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - layers segmentation in parallel - begin"; tbb::parallel_for(tbb::blocked_range(0, print_object.layers().size()), [&](const tbb::blocked_range &range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { throw_on_cancel_callback(); - // for(size_t layer_idx = 0; layer_idx < print_object.layers().size(); ++layer_idx) { - BOOST_LOG_TRIVIAL(debug) << "MMU segmentation of layer: " << layer_idx; auto comp = [&edge_grids, layer_idx](const PaintedLine &first, const PaintedLine &second) { Point first_start_p = *(edge_grids[layer_idx].contours()[first.contour_idx].begin() + first.line_idx); @@ -1530,6 +1543,7 @@ std::vector>> multi_material_segmentati } } }); // end of parallel_for + BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - layers segmentation in parallel - end"; throw_on_cancel_callback(); if (auto w = print_object.config().mmu_segmented_region_max_width; w > 0.f) { From e0973f6a270e576155431624773c196c3ed0a23f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Wed, 9 Jun 2021 17:13:30 +0200 Subject: [PATCH 08/11] Added using the move operator in some parts of multi-material segmentation. --- src/libslic3r/MultiMaterialSegmentation.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index 6f1ca61c0e1..be1b838fd7e 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -185,7 +185,8 @@ static bool vertex_equal_to_point(const Voronoi::VD::vertex_type &vertex, const ulp_cmp(vertex.y(), double(ipt.y()), ULPS) == ulp_cmp_type::EQUAL; } -static inline bool vertex_equal_to_point(const Voronoi::VD::vertex_type *vertex, const Point &ipt) { +static inline bool vertex_equal_to_point(const Voronoi::VD::vertex_type *vertex, const Point &ipt) +{ return vertex_equal_to_point(*vertex, ipt); } @@ -1137,11 +1138,10 @@ static void cut_segmented_layers(const std::vector std::vector> segmented_regions_cuts; for (const std::pair &colored_expoly : segmented_regions[layer_idx]) { ExPolygons cut_colored_expoly = diff_ex(colored_expoly.first, offset_ex(input_expolygons[layer_idx], cut_width)); - for (const ExPolygon &expoly : cut_colored_expoly) { - segmented_regions_cuts.emplace_back(expoly, colored_expoly.second); - } + for (ExPolygon &expoly : cut_colored_expoly) + segmented_regions_cuts.emplace_back(std::move(expoly), colored_expoly.second); } - segmented_regions[layer_idx] = segmented_regions_cuts; + segmented_regions[layer_idx] = std::move(segmented_regions_cuts); } }); // end of parallel_for BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - cutting segmented layers in parallel - end"; @@ -1519,9 +1519,8 @@ std::vector>> multi_material_segmentati tbb::parallel_for(tbb::blocked_range(0, print_object.layers().size()), [&](const tbb::blocked_range &range) { for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { throw_on_cancel_callback(); - auto comp = [&edge_grids, layer_idx](const PaintedLine &first, const PaintedLine &second) { - Point first_start_p = *(edge_grids[layer_idx].contours()[first.contour_idx].begin() + first.line_idx); - + auto comp = [&input_polygons, layer_idx](const PaintedLine &first, const PaintedLine &second) { + Point first_start_p = input_polygons[layer_idx][first.contour_idx][first.line_idx]; return first.contour_idx < second.contour_idx || (first.contour_idx == second.contour_idx && (first.line_idx < second.line_idx || @@ -1538,8 +1537,8 @@ std::vector>> multi_material_segmentati remove_multiple_edges_in_vertices(graph, color_poly); graph.remove_nodes_with_one_arc(); std::vector> segmentation = extract_colored_segments(graph); - for (const std::pair ®ion : segmentation) - segmented_regions[layer_idx].emplace_back(region); + for (std::pair ®ion : segmentation) + segmented_regions[layer_idx].emplace_back(std::move(region)); } } }); // end of parallel_for From 843048ade825f2e28fce082a6e52607b21552f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 10 Jun 2021 08:33:14 +0200 Subject: [PATCH 09/11] Fixed layers with the wrong color after multi-material segmentation on objects with multiple objects. --- src/libslic3r/MultiMaterialSegmentation.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index be1b838fd7e..211c238832d 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -236,6 +236,10 @@ static std::vector colorize_line(const Line & line_to_ std::vector filtered_lines; filtered_lines.emplace_back(internal_painted.front()); for (size_t line_idx = 1; line_idx < internal_painted.size(); ++line_idx) { + // line_to_process is already all colored. Skip another possible duplicate coloring. + if(filtered_lines.back().projected_line.b == line_to_process.b) + break; + PaintedLine &prev = filtered_lines.back(); PaintedLine &curr = internal_painted[line_idx]; @@ -1417,7 +1421,7 @@ std::vector>> multi_material_segmentati ExPolygons ex_polygons; for (LayerRegion *region : layers[layer_idx]->regions()) for (const Surface &surface : region->slices.surfaces) - Slic3r::append(ex_polygons, offset_ex(surface.expolygon, float(SCALED_EPSILON))); + Slic3r::append(ex_polygons, offset_ex(surface.expolygon, float(10 * SCALED_EPSILON))); // All expolygons are expanded by SCALED_EPSILON, merged, and then shrunk again by SCALED_EPSILON // to ensure that very close polygons will be merged. ex_polygons = union_ex(ex_polygons); @@ -1430,7 +1434,7 @@ std::vector>> multi_material_segmentati // Such close points sometimes caused that the Voronoi diagram has self-intersecting edges around these vertices. // This consequently leads to issues with the extraction of colored segments by function extract_colored_segments. // Calling expolygons_simplify fixed these issues. - input_expolygons[layer_idx] = simplify_polygons_ex(to_polygons(expolygons_simplify(offset_ex(ex_polygons, float(-SCALED_EPSILON)), SCALED_EPSILON))); + input_expolygons[layer_idx] = simplify_polygons_ex(to_polygons(expolygons_simplify(offset_ex(ex_polygons, float(-10 * SCALED_EPSILON)), 5 * SCALED_EPSILON))); input_polygons[layer_idx] = to_polygons(input_expolygons[layer_idx]); } }); // end of parallel_for @@ -1439,7 +1443,8 @@ std::vector>> multi_material_segmentati for (size_t layer_idx = 0; layer_idx < layers.size(); ++layer_idx) { throw_on_cancel_callback(); BoundingBox bbox(get_extents(input_expolygons[layer_idx])); - bbox.offset(SCALED_EPSILON); + // Projected triangles may slightly exceed the input polygons. + bbox.offset(20 * SCALED_EPSILON); edge_grids[layer_idx].set_bbox(bbox); edge_grids[layer_idx].create(input_expolygons[layer_idx], coord_t(scale_(10.))); } @@ -1525,7 +1530,9 @@ std::vector>> multi_material_segmentati (first.contour_idx == second.contour_idx && (first.line_idx < second.line_idx || (first.line_idx == second.line_idx && - Line(first_start_p, first.projected_line.a).length() < Line(first_start_p, second.projected_line.a).length()))); + ((first.projected_line.a - first_start_p).cast().squaredNorm() < (second.projected_line.a - first_start_p).cast().squaredNorm() || + ((first.projected_line.a - first_start_p).cast().squaredNorm() == (second.projected_line.a - first_start_p).cast().squaredNorm() && + (first.projected_line.b - first.projected_line.a).cast().squaredNorm() < (second.projected_line.b - second.projected_line.a).cast().squaredNorm()))))); }; std::sort(painted_lines[layer_idx].begin(), painted_lines[layer_idx].end(), comp); From 83af1070099136ceb891949b4170a81a3c7e8377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 10 Jun 2021 12:50:30 +0200 Subject: [PATCH 10/11] Fixed an issue for multi-volume objects where the seed fill visualization in the multi-material gizmo didn't disappear after the mouse was moved to another volume. --- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 19 +++++++++++++++---- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp | 4 ++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index 2c00e8f336c..3f8d5a0076c 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -393,9 +393,10 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous Vec3f camera_pos = (trafo_matrix.inverse() * camera.get_position()).cast(); assert(m_rr.mesh_id < int(m_triangle_selectors.size())); - if (m_seed_fill_enabled) + if (m_seed_fill_enabled) { m_triangle_selectors[m_rr.mesh_id]->seed_fill_apply_on_triangles(new_state); - else + m_seed_fill_last_mesh_id = -1; + } else m_triangle_selectors[m_rr.mesh_id]->select_patch(m_rr.hit, int(m_rr.facet), camera_pos, m_cursor_radius, m_cursor_type, new_state, trafo_matrix, m_triangle_splitting_enabled); m_last_mouse_click = mouse_position; @@ -423,17 +424,27 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous // Now "click" into all the prepared points and spill paint around them. update_raycast_cache(mouse_position, camera, trafo_matrices); - if (m_rr.mesh_id == -1) { - // Clean selected by seed fill for all triangles + auto seed_fill_unselect_all = [this]() { for (auto &triangle_selector : m_triangle_selectors) triangle_selector->seed_fill_unselect_all_triangles(); + }; + + if (m_rr.mesh_id == -1) { + // Clean selected by seed fill for all triangles in all meshes when a mouse isn't pointing on any mesh. + seed_fill_unselect_all(); + m_seed_fill_last_mesh_id = -1; // In case we have no valid hit, we can return. return false; } + // The mouse moved from one object's volume to another one. So it is needed to unselect all triangles selected by seed fill. + if(m_rr.mesh_id != m_seed_fill_last_mesh_id) + seed_fill_unselect_all(); + assert(m_rr.mesh_id < int(m_triangle_selectors.size())); m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), m_seed_fill_angle); + m_seed_fill_last_mesh_id = m_rr.mesh_id; return true; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp index 3bba3fde577..b64585e9f6a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.hpp @@ -103,6 +103,10 @@ protected: bool m_seed_fill_enabled = false; float m_seed_fill_angle = 0.f; + // It stores the value of the previous mesh_id to which the seed fill was applied. + // It is used to detect when the mouse has moved from one volume to another one. + int m_seed_fill_last_mesh_id = -1; + enum class Button { None, Left, From 4b82d9b280d5eafbb68493e49d2cda980176eb63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Tue, 15 Jun 2021 16:12:26 +0200 Subject: [PATCH 11/11] Fixed an issue where the color of the first extruder always replaced the default color after painting in a multi-material gizmo. multi_material_segmentation_by_painting is now returning only the painted region. Regions with default colors that aren't painted by multi-material gizmo aren't returned. --- src/libslic3r/MultiMaterialSegmentation.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index 211c238832d..f943934b52a 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -1385,16 +1385,19 @@ static std::vector>> merge_segmented_la for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) { for (const std::pair &colored_expoly : segmented_regions[layer_idx]) { throw_on_cancel_callback(); + // Zero is the default color of the volume. + if(colored_expoly.second == 0) + continue; ExPolygons cut_colored_expoly = {colored_expoly.first}; for (const std::vector &top_and_bottom_layer : top_and_bottom_layers) cut_colored_expoly = diff_ex(cut_colored_expoly, top_and_bottom_layer[layer_idx]); for (ExPolygon &ex_poly : cut_colored_expoly) - segmented_regions_merged[layer_idx].emplace_back(std::move(ex_poly), colored_expoly.second); + segmented_regions_merged[layer_idx].emplace_back(std::move(ex_poly), colored_expoly.second - 1); } - for (size_t color_idx = 0; color_idx < top_and_bottom_layers.size(); ++color_idx) + for (size_t color_idx = 1; color_idx < top_and_bottom_layers.size(); ++color_idx) for (ExPolygon &expoly : top_and_bottom_layers[color_idx][layer_idx]) - segmented_regions_merged[layer_idx].emplace_back(std::move(expoly), color_idx); + segmented_regions_merged[layer_idx].emplace_back(std::move(expoly), color_idx - 1); } }); // end of parallel_for BOOST_LOG_TRIVIAL(debug) << "MMU segmentation - merging segmented layers in parallel - end";