From 255ada5ff2d43f7a3eb31bfb9d93093de1d8d487 Mon Sep 17 00:00:00 2001 From: "zhou.xu" Date: Mon, 12 May 2025 16:18:09 +0800 Subject: [PATCH] ENH:Add sinking render in the paint gizmo jira: STUDIO-11649 Change-Id: I5edadc0107dd6ab8fc4e28d478135796463ee64b --- src/slic3r/GUI/3DScene.cpp | 79 +++++++++++++++++++ src/slic3r/GUI/3DScene.hpp | 12 ++- src/slic3r/GUI/GLCanvas3D.cpp | 21 +++++ src/slic3r/GUI/GLCanvas3D.hpp | 1 + src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 7 +- .../GUI/Gizmos/GLGizmoMmuSegmentation.cpp | 8 +- src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp | 2 +- src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp | 9 ++- src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp | 22 +++++- src/slic3r/GUI/Gizmos/GLGizmosManager.cpp | 5 +- src/slic3r/GUI/Gizmos/GLGizmosManager.hpp | 2 +- 11 files changed, 155 insertions(+), 13 deletions(-) diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index b377c3a0e..044124e7b 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -1624,6 +1624,36 @@ GLVolumeWithIdAndZList volumes_to_render(const GLVolumePtrs& volumes, GLVolumeCo return list; } +GLVolumeWithIdAndZList volumes_to_render_for_sinking(const GLVolumePtrs & volumes, + GLVolumeCollection::ERenderType type, + const Transform3d & view_matrix) +{ + GLVolumeWithIdAndZList list; + list.reserve(volumes.size()); + + for (unsigned int i = 0; i < (unsigned int) volumes.size(); ++i) { + GLVolume *volume = volumes[i]; + bool is_transparent = (volume->render_color[3] < 1.0f); + auto tempGlwipeTowerVolume = dynamic_cast(volume); + if (tempGlwipeTowerVolume) { + continue; + } + if (!volume->selected) + continue; + list.emplace_back(std::make_pair(volume, std::make_pair(i, 0.0))); + } + + if (type == GLVolumeCollection::ERenderType::Transparent && list.size() > 1) { + for (GLVolumeWithIdAndZ &volume : list) { volume.second.second = volume.first->bounding_box().transformed(view_matrix * volume.first->world_matrix()).max(2); } + + std::sort(list.begin(), list.end(), [](const GLVolumeWithIdAndZ &v1, const GLVolumeWithIdAndZ &v2) -> bool { return v1.second.second < v2.second.second; }); + } else if (type == GLVolumeCollection::ERenderType::Opaque && list.size() > 1) { + std::sort(list.begin(), list.end(), [](const GLVolumeWithIdAndZ &v1, const GLVolumeWithIdAndZ &v2) -> bool { return v1.first->selected && !v2.first->selected; }); + } + + return list; +} + int GLVolumeCollection::get_selection_support_threshold_angle(bool &enable_support) const { const DynamicPrintConfig& glb_cfg = GUI::wxGetApp().preset_bundle->prints.get_edited_preset().config; @@ -1805,6 +1835,55 @@ void GLVolumeCollection::render(GUI::ERenderPipelineStage render_pip glsafe(::glDisable(GL_BLEND)); } +void GLVolumeCollection::only_render_sinking(GUI::ERenderPipelineStage render_pipeline_stage, + ERenderType type, + bool disable_cullface, + const GUI::Camera & camera, + const std::vector> &colors, + Model & model, + std::function filter_func, + bool with_outline, + const std::array & body_color, + bool partly_inside_enable, + std::vector * printable_heights) +{ + auto view_matrix = camera.get_view_matrix(); + auto projection_matrix = camera.get_projection_matrix(); + GLVolumeWithIdAndZList to_render = volumes_to_render_for_sinking(volumes, type, view_matrix); + if (to_render.empty()) + return; + + const auto shader = GUI::wxGetApp().get_current_shader(); + if (shader == nullptr) + return; + + if (type == ERenderType::Transparent) { + glsafe(::glEnable(GL_BLEND)); + glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + } + + glsafe(::glDisable(GL_CULL_FACE)); + if (GUI::ERenderPipelineStage::Silhouette != render_pipeline_stage) { + if (m_show_sinking_contours) { + for (GLVolumeWithIdAndZ &volume : to_render) { + if (volume.first->is_sinking() && !volume.first->is_below_printbed()) { + GUI::wxGetApp().unbind_shader(); + glsafe(::glDepthFunc(GL_ALWAYS)); + volume.first->render_sinking_contours(camera, model); + glsafe(::glDepthFunc(GL_LESS)); + GUI::wxGetApp().bind_shader(shader); + } + } + } + } + + if (disable_cullface) + glsafe(::glEnable(GL_CULL_FACE)); + + if (type == ERenderType::Transparent) + glsafe(::glDisable(GL_BLEND)); +} + bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, ModelInstanceEPrintVolumeState *out_state, ObjectFilamentResults *object_results, Model &model) const { if (GUI::wxGetApp().plater() == NULL) diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index e6b0219e9..61d676bb9 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -747,7 +747,17 @@ public: const std::array & body_color = {1.0f, 1.0f, 1.0f, 1.0f}, bool partly_inside_enable = true, std::vector * printable_heights = nullptr); - + void only_render_sinking(GUI::ERenderPipelineStage render_pipeline_stage, + ERenderType type, + bool disable_cullface, + const GUI::Camera & camera, + const std::vector> &colors, + Model & model, + std::function filter_func = std::function(), + bool with_outline = true, + const std::array & body_color = {1.0f, 1.0f, 1.0f, 1.0f}, + bool partly_inside_enable = true, + std::vector * printable_heights = nullptr); // Finalize the initialization of the geometry & indices, // upload the geometry and indices to OpenGL VBO objects // and shrink the allocated data, possibly relasing it if it has been loaded into the VBOs. diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 23c51354f..11fea8c27 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1724,6 +1724,15 @@ ModelInstanceEPrintVolumeState GLCanvas3D::check_volumes_outside_state(ObjectFil return state; } +bool GLCanvas3D::is_volumes_selected_and_sinking() const { + for (GLVolume *volume : m_volumes.volumes) { + if (volume->selected && volume->is_sinking() && !volume->is_below_printbed()) { + return true; + } + } + return false; +} + void GLCanvas3D::toggle_selected_volume_visibility(bool selected_visible) { m_render_sla_auxiliaries = !selected_visible; @@ -7570,6 +7579,18 @@ void GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type, bool with gm.render_painter_assemble_view(); wxGetApp().bind_shader(shader); } + if (m_canvas_type == CanvasView3D && m_gizmos.is_paint_gizmo()) { + m_volumes.only_render_sinking( + render_pipeline_stage, type, false, camera, colors, *m_model, + [this, canvas_type](const GLVolume &volume) { + if (canvas_type == ECanvasType::CanvasAssembleView) { + return !volume.is_modifier; + } else { + return true; + } + }, + with_outline, body_color, partly_inside_enable, printable_height_option ? &printable_height_option->values : nullptr); + } break; } } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 0fc5176df..8c0519804 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -807,6 +807,7 @@ public: void reset_volumes(bool set_notice = true); ModelInstanceEPrintVolumeState check_volumes_outside_state(ObjectFilamentResults* object_results = nullptr) const; bool is_all_plates_selected() { return m_sel_plate_toolbar.m_all_plates_stats_item && m_sel_plate_toolbar.m_all_plates_stats_item->selected; } + bool is_volumes_selected_and_sinking() const; const float get_scale() const; //BBS diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 086835269..8c3708fea 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -283,7 +283,7 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l const float sliders_width = m_imgui->scaled(7.0f); const float drag_left_width = ImGui::GetStyle().WindowPadding.x + sliders_left_width + sliders_width - space_size; - + float window_width = minimal_slider_width + sliders_left_width + slider_icon_width; float drag_pos_times = 0.7; ImGui::AlignTextToFramePadding(); @@ -462,6 +462,11 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l } ImGui::Separator(); + if (m_parent.is_volumes_selected_and_sinking()) { + m_imgui->warning_text_wrapped(_L("Warning") + ":" + _L("Painting below the build plate is not allowed.") + + _L("The white outline indicates the position of the build plate at Z = 0."), + window_width+ m_imgui->scaled(3)); + } ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f)); float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y; show_tooltip_information(caption_max, x, get_cur_y); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp index 742a723c2..2e1c41c1a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMmuSegmentation.cpp @@ -479,7 +479,7 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott window_width = std::max(window_width, total_text_max); window_width = std::max(window_width, buttons_width); - window_width = std::max(window_width, max_filament_items_per_line * filament_item_width + +m_imgui->scaled(0.5f)); + window_width = std::max(window_width, max_filament_items_per_line * filament_item_width + m_imgui->scaled(0.5f)); const float sliders_width = m_imgui->scaled(7.0f); const float drag_left_width = ImGui::GetStyle().WindowPadding.x + sliders_width - space_size; @@ -840,7 +840,11 @@ void GLGizmoMmuSegmentation::on_render_input_window(float x, float y, float bott m_imgui->disabled_end(); ImGui::Separator(); } - + if (m_parent.is_volumes_selected_and_sinking()) { + m_imgui->warning_text_wrapped(_L("Warning") + ":" + _L("Painting below the build plate is not allowed.") + + _L("The white outline indicates the position of the build plate at Z = 0."), + window_width + m_imgui->scaled(1)); + } ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f)); float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y; show_tooltip_information(caption_max, x, get_cur_y); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index cd5b921ed..9a694966a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -65,7 +65,7 @@ GLGizmoPainterBase::ClippingPlaneDataWrapper GLGizmoPainterBase::get_clipping_pl // z_range is calculated in the same way as in GLCanvas3D::_render_objects(GLVolumeCollection::ERenderType type) if (m_c->get_canvas()->get_use_clipping_planes()) { const std::array &clps = m_c->get_canvas()->get_clipping_planes(); - clp_data_out.z_range = {float(-clps[0].get_data()[3]), float(clps[1].get_data()[3])}; + clp_data_out.z_range = {-FLT_MAX, float(clps[1].get_data()[3])}; } return clp_data_out; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp index f5507deaf..6ded66741 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoSeam.cpp @@ -230,10 +230,10 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) const float sliders_left_width = std::max(cursor_size_slider_left, clipping_slider_left); const float slider_icon_width = m_imgui->get_slider_icon_size().x; - + const float minimal_slider_width = m_imgui->scaled(4.f); const float sliders_width = m_imgui->scaled(7.0f); const float drag_left_width = ImGui::GetStyle().WindowPadding.x + sliders_left_width + sliders_width - space_size; - + float window_width = minimal_slider_width + sliders_left_width + slider_icon_width; const float max_tooltip_width = ImGui::GetFontSize() * 20.0f; float textbox_width = 1.5 * slider_icon_width; @@ -353,6 +353,11 @@ void GLGizmoSeam::on_render_input_window(float x, float y, float bottom_limit) } m_imgui->disabled_end(); ImGui::Separator(); + if (m_parent.is_volumes_selected_and_sinking()) { + m_imgui->warning_text_wrapped(_L("Warning") + ":" + _L("Painting below the build plate is not allowed.") + + _L("The white outline indicates the position of the build plate at Z = 0."), + window_width + m_imgui->scaled(3)); + } ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.0f, 10.0f)); float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y; show_tooltip_information(caption_max, x, get_cur_y); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index c0d88108f..683ce2d75 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -154,8 +154,13 @@ void InstancesHider::on_update() double z_min; if (canvas->get_canvas_type() == GLCanvas3D::CanvasAssembleView) z_min = std::numeric_limits::max(); - else - z_min = -SINKING_Z_THRESHOLD; + else { + if (canvas->get_gizmos_manager().is_paint_gizmo()) { + z_min = -FLT_MAX; + } else { + z_min = -SINKING_Z_THRESHOLD; + } + } if (mo && active_inst != -1) { canvas->toggle_model_objects_visibility(false); @@ -420,7 +425,8 @@ void CommonGizmosDataObjects::ObjectClipper::render_cut(const std::vectormodel_object(); Geometry::Transformation inst_trafo; - bool is_assem_cnv = get_pool()->get_canvas()->get_canvas_type() == GLCanvas3D::CanvasAssembleView; + GLCanvas3D * canvas = get_pool()->get_canvas(); + bool is_assem_cnv = canvas->get_canvas_type() == GLCanvas3D::CanvasAssembleView; inst_trafo = is_assem_cnv ? mo->instances[sel_info->get_active_instance()]->get_assemble_transformation() : mo->instances[sel_info->get_active_instance()]->get_transformation(); auto offset_to_assembly = mo->instances[0]->get_offset_to_assembly(); @@ -428,6 +434,14 @@ void CommonGizmosDataObjects::ObjectClipper::render_cut(const std::vectorget_sla_shift(); std::vector ignore_idxs_local = ignore_idxs ? *ignore_idxs : std::vector(); + + double z_min; + if (canvas->get_gizmos_manager().is_paint_gizmo()) { + z_min = -FLT_MAX; + } else { + z_min = -SINKING_Z_THRESHOLD; + } + for (auto &clipper : m_clippers) { auto vol_trafo = clipper.second; Geometry::Transformation trafo = inst_trafo * vol_trafo; @@ -438,7 +452,7 @@ void CommonGizmosDataObjects::ObjectClipper::render_cut(const std::vectorset_plane(*m_clp); clipper.first->set_transformation(trafo); - clipper.first->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD)); + clipper.first->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), z_min)); clipper.first->render_cut(OpenGLManager::get_cut_plane_color(), &ignore_idxs_local); clipper.first->render_contour({1.f, 1.f, 1.f, 1.f}, &ignore_idxs_local); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp index 86affeba0..a53ed4b9a 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.cpp @@ -727,7 +727,7 @@ bool GLGizmosManager::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_p return false; } -bool GLGizmosManager::is_paint_gizmo() +bool GLGizmosManager::is_paint_gizmo() const { return m_current == EType::FdmSupports || m_current == EType::MmuSegmentation || @@ -1912,6 +1912,9 @@ bool GLGizmosManager::is_in_editing_mode(bool error_notification) const bool GLGizmosManager::is_hiding_instances() const { + if (is_paint_gizmo()) { + return false; + } return (m_common_gizmos_data && m_common_gizmos_data->instances_hider() && m_common_gizmos_data->instances_hider()->is_valid()); diff --git a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp index ab41f598e..77942940e 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosManager.hpp @@ -291,7 +291,7 @@ public: void check_object_located_outside_plate(bool change_plate =true); bool get_object_located_outside_plate() { return m_object_located_outside_plate; } bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position = Vec2d::Zero(), bool shift_down = false, bool alt_down = false, bool control_down = false); - bool is_paint_gizmo(); + bool is_paint_gizmo()const; bool is_allow_select_all(); ClippingPlane get_clipping_plane() const; ClippingPlane get_assemble_view_clipping_plane() const;