diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 7ef98db151..50265cb670 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -913,6 +913,11 @@ public: // Returns 0-based indices of extruders painted by multi-material painting gizmo. std::vector get_extruders_from_multi_material_painting() const; + static size_t get_extruder_color_idx(const ModelVolume& model_volume, const int extruders_count) { + const int extruder_id = model_volume.extruder_id(); + return (extruder_id <= 0 || extruder_id > extruders_count) ? 0 : extruder_id - 1; + } + protected: friend class Print; friend class SLAPrint; diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index b27afd7c3c..01c6248129 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -18,6 +18,8 @@ #include "BitmapCache.hpp" #include "Camera.hpp" +#include "Gizmos/GLGizmoMmuSegmentation.hpp" + #include "libslic3r/BuildVolume.hpp" #include "libslic3r/ExtrusionEntity.hpp" #include "libslic3r/ExtrusionEntityCollection.hpp" @@ -748,16 +750,19 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab if (to_render.empty()) return; - GLShaderProgram* shader = GUI::wxGetApp().get_current_shader(); - if (shader == nullptr) - return; - + GLShaderProgram* curr_shader = GUI::wxGetApp().get_current_shader(); GLShaderProgram* sink_shader = GUI::wxGetApp().get_shader("flat"); #if SLIC3R_OPENGL_ES GLShaderProgram* edges_shader = GUI::wxGetApp().get_shader("dashed_lines"); #else GLShaderProgram* edges_shader = GUI::OpenGLManager::get_gl_info().is_core_profile() ? GUI::wxGetApp().get_shader("dashed_thick_lines") : GUI::wxGetApp().get_shader("flat"); #endif // SLIC3R_OPENGL_ES + GLShaderProgram* mmu_painted_shader = GUI::wxGetApp().get_shader("mm_gouraud"); + if (curr_shader == nullptr || sink_shader == nullptr || edges_shader == nullptr || mmu_painted_shader == nullptr) + return; + + GLShaderProgram* shader = curr_shader; + shader->stop_using(); if (type == ERenderType::Transparent) { glsafe(::glEnable(GL_BLEND)); @@ -769,12 +774,25 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab if (disable_cullface) glsafe(::glDisable(GL_CULL_FACE)); + const ModelObjectPtrs& model_objects = GUI::wxGetApp().model().objects; + const std::vector extruders_colors = GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); + const bool is_render_as_mmu_painted_enabled = !model_objects.empty() && !extruders_colors.empty(); + for (GLVolumeWithIdAndZ& volume : to_render) { - const Transform3d& world_matrix = volume.first->world_matrix(); + if (!volume.first->is_active) + continue; + + const Transform3d world_matrix = volume.first->world_matrix(); + const Matrix3d world_matrix_inv_transp = world_matrix.linear().inverse().transpose(); + const Matrix3d view_normal_matrix = view_matrix.linear() * world_matrix_inv_transp; + const int obj_idx = volume.first->object_idx(); + const int vol_idx = volume.first->volume_idx(); + const bool render_as_mmu_painted = is_render_as_mmu_painted_enabled && !volume.first->selected && + !volume.first->is_outside && !volume.first->is_wipe_tower && obj_idx >= 0 && vol_idx >= 0 && + !model_objects[obj_idx]->volumes[vol_idx]->mm_segmentation_facets.empty(); volume.first->set_render_color(true); // render sinking contours of non-hovered volumes - shader->stop_using(); if (sink_shader != nullptr) { sink_shader->start_using(); if (m_show_sinking_contours) { @@ -785,50 +803,83 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab } sink_shader->stop_using(); } - shader->start_using(); - shader->set_uniform("z_range", m_z_range); - shader->set_uniform("clipping_plane", m_clipping_plane); - shader->set_uniform("use_color_clip_plane", m_use_color_clip_plane); - shader->set_uniform("color_clip_plane", m_color_clip_plane); - shader->set_uniform("uniform_color_clip_plane_1", m_color_clip_plane_colors[0]); - shader->set_uniform("uniform_color_clip_plane_2", m_color_clip_plane_colors[1]); - shader->set_uniform("print_volume.type", static_cast(m_print_volume.type)); - shader->set_uniform("print_volume.xy_data", m_print_volume.data); - shader->set_uniform("print_volume.z_data", m_print_volume.zs); - shader->set_uniform("volume_world_matrix", world_matrix); - shader->set_uniform("slope.actived", m_slope.active && !volume.first->is_modifier && !volume.first->is_wipe_tower); - shader->set_uniform("slope.volume_world_normal_matrix", static_cast(world_matrix.matrix().block(0, 0, 3, 3).inverse().transpose().cast())); - shader->set_uniform("slope.normal_z", m_slope.normal_z); + if (render_as_mmu_painted && shader != mmu_painted_shader) + shader = mmu_painted_shader; + else if (!render_as_mmu_painted && shader != curr_shader) + shader = curr_shader; + + if (render_as_mmu_painted) { + shader->start_using(); + const std::array clp_data = { 0.0f, 0.0f, 1.0f, FLT_MAX }; + const std::array z_range = { -FLT_MAX, FLT_MAX }; + const bool is_left_handed = volume.first->is_left_handed(); + shader->set_uniform("volume_world_matrix", world_matrix); + shader->set_uniform("volume_mirrored", is_left_handed); + shader->set_uniform("clipping_plane", clp_data); + shader->set_uniform("z_range", z_range); + shader->set_uniform("view_model_matrix", view_matrix * world_matrix); + shader->set_uniform("projection_matrix", projection_matrix); + shader->set_uniform("view_normal_matrix", view_normal_matrix); + + if (is_left_handed) + glsafe(::glFrontFace(GL_CW)); + + const ModelVolume& model_volume = *model_objects[obj_idx]->volumes[vol_idx]; + const size_t extruder_idx = ModelVolume::get_extruder_color_idx(model_volume, GUI::wxGetApp().extruders_edited_cnt()); + GUI::TriangleSelectorMmGui ts(model_volume.mesh(), extruders_colors, extruders_colors[extruder_idx]); + ts.deserialize(model_volume.mm_segmentation_facets.get_data(), true); + ts.request_update_render_data(); + ts.render(nullptr, world_matrix); + + if (is_left_handed) + glsafe(::glFrontFace(GL_CCW)); + + shader->stop_using(); + } + else { + shader->start_using(); + shader->set_uniform("z_range", m_z_range); + shader->set_uniform("clipping_plane", m_clipping_plane); + shader->set_uniform("use_color_clip_plane", m_use_color_clip_plane); + shader->set_uniform("color_clip_plane", m_color_clip_plane); + shader->set_uniform("uniform_color_clip_plane_1", m_color_clip_plane_colors[0]); + shader->set_uniform("uniform_color_clip_plane_2", m_color_clip_plane_colors[1]); + shader->set_uniform("print_volume.type", static_cast(m_print_volume.type)); + shader->set_uniform("print_volume.xy_data", m_print_volume.data); + shader->set_uniform("print_volume.z_data", m_print_volume.zs); + shader->set_uniform("volume_world_matrix", world_matrix); + shader->set_uniform("slope.actived", m_slope.active && !volume.first->is_modifier && !volume.first->is_wipe_tower); + shader->set_uniform("slope.volume_world_normal_matrix", static_cast(world_matrix_inv_transp.cast())); + shader->set_uniform("slope.normal_z", m_slope.normal_z); #if ENABLE_ENVIRONMENT_MAP - unsigned int environment_texture_id = GUI::wxGetApp().plater()->get_environment_texture_id(); - bool use_environment_texture = environment_texture_id > 0 && GUI::wxGetApp().app_config->get_bool("use_environment_map"); - shader->set_uniform("use_environment_tex", use_environment_texture); - if (use_environment_texture) - glsafe(::glBindTexture(GL_TEXTURE_2D, environment_texture_id)); + unsigned int environment_texture_id = GUI::wxGetApp().plater()->get_environment_texture_id(); + bool use_environment_texture = environment_texture_id > 0 && GUI::wxGetApp().app_config->get_bool("use_environment_map"); + shader->set_uniform("use_environment_tex", use_environment_texture); + if (use_environment_texture) + glsafe(::glBindTexture(GL_TEXTURE_2D, environment_texture_id)); #endif // ENABLE_ENVIRONMENT_MAP - glcheck(); + glcheck(); - volume.first->model.set_color(volume.first->render_color); - const Transform3d model_matrix = world_matrix; - shader->set_uniform("view_model_matrix", view_matrix * model_matrix); - shader->set_uniform("projection_matrix", projection_matrix); - const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); - shader->set_uniform("view_normal_matrix", view_normal_matrix); - volume.first->render(); + volume.first->model.set_color(volume.first->render_color); + shader->set_uniform("view_model_matrix", view_matrix * world_matrix); + shader->set_uniform("projection_matrix", projection_matrix); + shader->set_uniform("view_normal_matrix", view_normal_matrix); + volume.first->render(); #if ENABLE_ENVIRONMENT_MAP - if (use_environment_texture) - glsafe(::glBindTexture(GL_TEXTURE_2D, 0)); + if (use_environment_texture) + glsafe(::glBindTexture(GL_TEXTURE_2D, 0)); #endif // ENABLE_ENVIRONMENT_MAP - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + shader->stop_using(); + } } if (m_show_sinking_contours) { - shader->stop_using(); if (sink_shader != nullptr) { sink_shader->start_using(); for (GLVolumeWithIdAndZ& volume : to_render) { @@ -840,12 +891,10 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab glsafe(::glDepthFunc(GL_LESS)); } } - sink_shader->start_using(); + sink_shader->stop_using(); } - shader->start_using(); } - shader->stop_using(); if (edges_shader != nullptr) { edges_shader->start_using(); if (m_show_non_manifold_edges && GUI::wxGetApp().app_config->get_bool("non_manifold_edges")) { @@ -855,7 +904,8 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab } edges_shader->stop_using(); } - shader->start_using(); + + curr_shader->start_using(); if (disable_cullface) glsafe(::glEnable(GL_CULL_FACE)); diff --git a/src/slic3r/GUI/FrequentlyChangedParameters.cpp b/src/slic3r/GUI/FrequentlyChangedParameters.cpp index b7b74b2c2c..def49b0e9b 100644 --- a/src/slic3r/GUI/FrequentlyChangedParameters.cpp +++ b/src/slic3r/GUI/FrequentlyChangedParameters.cpp @@ -175,7 +175,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) const bool use_custom_matrix = (project_config.option("wiping_volumes_use_custom_matrix"))->value; const std::vector &init_matrix = (project_config.option("wiping_volumes_matrix"))->values; - const std::vector extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config(); + const std::vector extruder_colours = wxGetApp().plater()->get_extruder_color_strings_from_plater_config(); // Extract the relevant config options, even values from possibly modified presets. const double default_purge = static_cast(preset_bundle->printers.get_edited_preset().config.option("multimaterial_purging"))->value; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 5a84b6b84b..549c8d05ae 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4674,7 +4674,7 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const camera.apply_projection(volumes_box, near_z, far_z); const ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects; - std::vector extruders_colors = get_extruders_colors(); + std::vector extruders_colors = GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); const bool is_enabled_painted_thumbnail = !model_objects.empty() && !extruders_colors.empty(); if (thumbnail_params.transparent_background) @@ -4724,7 +4724,7 @@ void GLCanvas3D::_render_thumbnail_internal(ThumbnailData& thumbnail_data, const if (render_as_painted) { const ModelVolume& model_volume = *model_objects[obj_idx]->volumes[vol_idx]; - const size_t extruder_idx = get_extruder_color_idx(model_volume, extruders_count); + const size_t extruder_idx = ModelVolume::get_extruder_color_idx(model_volume, extruders_count); TriangleSelectorMmGui ts(model_volume.mesh(), extruders_colors, extruders_colors[extruder_idx]); ts.deserialize(model_volume.mm_segmentation_facets.get_data(), true); ts.request_update_render_data(); diff --git a/src/slic3r/GUI/GUI_Preview.cpp b/src/slic3r/GUI/GUI_Preview.cpp index f927171927..a9968afe69 100644 --- a/src/slic3r/GUI/GUI_Preview.cpp +++ b/src/slic3r/GUI/GUI_Preview.cpp @@ -419,7 +419,7 @@ void Preview::create_sliders() }); m_layers_slider->set_callback_on_get_extruder_colors([]() -> std::vector { - return wxGetApp().plater()->get_extruder_colors_from_plater_config(); + return wxGetApp().plater()->get_extruder_color_strings_from_plater_config(); }); m_layers_slider->set_callback_on_get_print([]() -> const Print& { @@ -603,7 +603,7 @@ void Preview::update_layers_slider(const std::vector& layers_z, bool kee check_layers_slider_values(ticks_info_from_model.gcodes, layers_z); //first of all update extruder colors to avoid crash, when we are switching printer preset from MM to SM - m_layers_slider->SetExtruderColors(plater->get_extruder_colors_from_plater_config(wxGetApp().is_editor() ? nullptr : m_gcode_result)); + m_layers_slider->SetExtruderColors(plater->get_extruder_color_strings_from_plater_config(wxGetApp().is_editor() ? nullptr : m_gcode_result)); m_layers_slider->SetSliderValues(layers_z); assert(m_layers_slider->GetMinPos() == 0); @@ -933,12 +933,12 @@ void Preview::load_print_as_fff(bool keep_z_range) const bool gcode_preview_data_valid = !m_gcode_result->moves.empty(); const bool is_pregcode_preview = !gcode_preview_data_valid && wxGetApp().is_editor(); - const std::vector tool_colors = wxGetApp().plater()->get_extruder_colors_from_plater_config(m_gcode_result); + const std::vector tool_colors = wxGetApp().plater()->get_extruder_color_strings_from_plater_config(m_gcode_result); const std::vector& color_print_values = wxGetApp().is_editor() ? wxGetApp().plater()->model().custom_gcode_per_print_z.gcodes : m_gcode_result->custom_gcode_per_print_z; std::vector color_print_colors; if (!color_print_values.empty()) { - color_print_colors = wxGetApp().plater()->get_colors_for_color_print(m_gcode_result); + color_print_colors = wxGetApp().plater()->get_color_strings_for_color_print(m_gcode_result); color_print_colors.push_back("#808080"); // gray color for pause print or custom G-code } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 2880c9ea42..6c0031d3f2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -62,14 +62,6 @@ bool GLGizmoMmuSegmentation::on_is_activable() const return GLGizmoPainterBase::on_is_activable() && wxGetApp().extruders_edited_cnt() > 1; } -std::vector get_extruders_colors() -{ - std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); - std::vector ret; - decode_colors(colors, ret); - return ret; -} - static std::vector get_extruders_names() { size_t extruders_count = wxGetApp().extruders_edited_cnt(); @@ -98,7 +90,7 @@ static std::vector get_extruder_id_for_volumes(const ModelObject &model_obj void GLGizmoMmuSegmentation::init_extruders_data() { m_original_extruders_names = get_extruders_names(); - m_original_extruders_colors = get_extruders_colors(); + m_original_extruders_colors = wxGetApp().plater()->get_extruder_colors_from_plater_config(); m_modified_extruders_colors = m_original_extruders_colors; m_first_selected_extruder_idx = 0; m_second_selected_extruder_idx = 1; @@ -160,7 +152,7 @@ void GLGizmoMmuSegmentation::data_changed(bool is_serializing) ModelObject *model_object = m_c->selection_info()->model_object(); if (int prev_extruders_count = int(m_original_extruders_colors.size()); - prev_extruders_count != wxGetApp().extruders_edited_cnt() || get_extruders_colors() != m_original_extruders_colors) { + prev_extruders_count != wxGetApp().extruders_edited_cnt() || wxGetApp().plater()->get_extruder_colors_from_plater_config() != m_original_extruders_colors) { if (wxGetApp().extruders_edited_cnt() > int(GLGizmoMmuSegmentation::EXTRUDERS_LIMIT)) show_notification_extruders_limit_exceeded(); @@ -544,7 +536,7 @@ 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_idx = get_extruder_color_idx(*mv, extruders_count); + const size_t extruder_idx = ModelVolume::get_extruder_color_idx(*mv, extruders_count); m_triangle_selectors.emplace_back(std::make_unique(*mesh, m_modified_extruders_colors, m_original_extruders_colors[extruder_idx])); // Reset of TriangleSelector is done inside TriangleSelectorMmGUI's constructor, so we don't need it to perform it again in deserialize(). m_triangle_selectors.back()->deserialize(mv->mm_segmentation_facets.get_data(), false); @@ -560,7 +552,7 @@ void GLGizmoMmuSegmentation::update_from_model_object() // Extruder colors need to be reloaded before calling init_model_triangle_selectors to render painted triangles // using colors from loaded 3MF and not from printer profile in Slicer. if (int prev_extruders_count = int(m_original_extruders_colors.size()); - prev_extruders_count != wxGetApp().extruders_edited_cnt() || get_extruders_colors() != m_original_extruders_colors) + prev_extruders_count != wxGetApp().extruders_edited_cnt() || wxGetApp().plater()->get_extruder_colors_from_plater_config() != m_original_extruders_colors) this->init_extruders_data(); this->init_model_triangle_selectors(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp index ad4931058d..7bec4c78b6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.hpp @@ -152,16 +152,6 @@ private: std::map m_desc; }; -std::vector get_extruders_colors(); - -inline size_t get_extruder_color_idx(const ModelVolume &model_volume, const int extruders_count) -{ - if (const int extruder_id = model_volume.extruder_id(); extruder_id <= 0 || extruder_id > extruders_count) - return 0; - else - return extruder_id - 1; -} - } // namespace Slic3r diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 56b66db03b..2bb4db5293 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6308,7 +6308,7 @@ void Plater::on_activate(bool active) } // Get vector of extruder colors considering filament color, if extruder color is undefined. -std::vector Plater::get_extruder_colors_from_plater_config(const GCodeProcessorResult* const result) const +std::vector Plater::get_extruder_color_strings_from_plater_config(const GCodeProcessorResult* const result) const { if (wxGetApp().is_gcode_viewer() && result != nullptr) return result->extruder_colors; @@ -6334,9 +6334,9 @@ std::vector Plater::get_extruder_colors_from_plater_config(const GC /* Get vector of colors used for rendering of a Preview scene in "Color print" mode * It consists of extruder colors and colors, saved in model.custom_gcode_per_print_z */ -std::vector Plater::get_colors_for_color_print(const GCodeProcessorResult* const result) const +std::vector Plater::get_color_strings_for_color_print(const GCodeProcessorResult* const result) const { - std::vector colors = get_extruder_colors_from_plater_config(result); + std::vector colors = get_extruder_color_strings_from_plater_config(result); colors.reserve(colors.size() + p->model.custom_gcode_per_print_z.gcodes.size()); if (wxGetApp().is_gcode_viewer() && result != nullptr) { @@ -6355,6 +6355,22 @@ std::vector Plater::get_colors_for_color_print(const GCodeProcessor return colors; } +std::vector Plater::get_extruder_colors_from_plater_config() const +{ + std::vector colors = get_extruder_color_strings_from_plater_config(); + std::vector ret; + decode_colors(colors, ret); + return ret; +} + +std::vector Plater::get_colors_for_color_print() const +{ + std::vector colors = get_color_strings_for_color_print(); + std::vector ret; + decode_colors(colors, ret); + return ret; +} + wxString Plater::get_project_filename(const wxString& extension) const { return p->get_project_filename(extension); diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index d841d17378..4b93b5a6e7 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -254,8 +254,11 @@ public: void force_print_bed_update(); // On activating the parent window. void on_activate(bool active); - std::vector get_extruder_colors_from_plater_config(const GCodeProcessorResult* const result = nullptr) const; - std::vector get_colors_for_color_print(const GCodeProcessorResult* const result = nullptr) const; + + std::vector get_extruder_color_strings_from_plater_config(const GCodeProcessorResult* const result = nullptr) const; + std::vector get_color_strings_for_color_print(const GCodeProcessorResult* const result = nullptr) const; + std::vector get_extruder_colors_from_plater_config() const; + std::vector get_colors_for_color_print() const; void update_menus(); void show_action_buttons(const bool is_ready_to_slice) const; diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 4ecf3d93cf..a4bfe74f38 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -329,7 +329,7 @@ std::vector get_extruder_color_icons(bool thin_icon/* = false*/ { // Create the bitmap with color bars. std::vector bmps; - std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); + std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_color_strings_from_plater_config(); if (colors.empty()) return bmps;