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] 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 976e35391..52085b178 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 0b6d7660b..e3af11468 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 0d28da252..811e4cd28 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;