From c751f2d638b1969df190a4a30e8223f1fae91609 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 53fbc4c1cb..bd0e4923bd 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 e04a5c49d2..3cf466dc38 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 f703ddcdbc..482de650df 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 11a9225caf..a858b26197 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 de9ed9ee3e8dfab13a35c2450c9d6680689b5568 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 3cf466dc38..ad726c110c 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 7377fc34acef999774333466db18858a1dae5512 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 daf8c59915..9662bacc0d 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 ad726c110c..0b6d7660bf 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 64b41e46e9..dfb87880fe 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 8e2d05ea83..6622f7326d 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 b2677f513cb1c87e1ccd5cc4d2ec363d16e7aa19 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 82b858d421..0d28da2526 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 6622f7326d..88790dde5b 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 8a77fa38f0ec050957fa2885b27296d9836d2c4d 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 976e353913..52085b1785 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 0b6d7660bf..e3af114682 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 0d28da2526..811e4cd280 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 15a1b513396bc2f096019f23542e2b9e1a8c3d87 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 8c903470dd..3274f000c6 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 e3af114682..50d74e0470 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 811e4cd280..f5c97801bc 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 dfb87880fe..2c00e8f336 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 88790dde5b..3bba3fde57 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 7a274c9270..d3c0c7d041 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 a06e42d01f6f8b32f30dc2fbde8310223d3ccaa4 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 a4237880f4..6f1ca61c0e 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 21b38db4884b26f434e6a2da6657d83cde906970 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 6f1ca61c0e..be1b838fd7 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 c59cf5de406a895b0e85f7712eca7d154e416879 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 be1b838fd7..211c238832 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 ae1a799cf4fb3ddd99fe8a1c19d92a3d383597d1 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 2c00e8f336..3f8d5a0076 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 3bba3fde57..b64585e9f6 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 6ddd88e596af04018ce199faf2542a0f9041fc59 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 211c238832..f943934b52 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";