diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 073429fc73..e02a4c6226 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -208,7 +208,7 @@ void AppConfig::set_defaults() { const std::string mode = get("preview_reduced_detail_mode"); - if (mode != "layers" && mode != "no_infill" && mode != "shell") + if (mode != "layers" && mode != "no_infill" && mode != "shell" && mode != "solid") set("preview_reduced_detail_mode", "no_infill"); } diff --git a/src/libvgcode/include/Types.hpp b/src/libvgcode/include/Types.hpp index 0a3d4fe15e..d54ae181a8 100644 --- a/src/libvgcode/include/Types.hpp +++ b/src/libvgcode/include/Types.hpp @@ -172,6 +172,9 @@ enum class EReducedDetailMode : uint8_t NoInternalInfill, // only the segments on the visible surface of the print are kept ShellOnly, + // only the bottom and top of the visible layer range are kept, for a caller that draws the + // print itself some other way and needs just the two faces the range cuts open + EndLayersOnly, COUNT }; diff --git a/src/libvgcode/src/ViewerImpl.cpp b/src/libvgcode/src/ViewerImpl.cpp index 8c1681202b..a3826f65ac 100644 --- a/src/libvgcode/src/ViewerImpl.cpp +++ b/src/libvgcode/src/ViewerImpl.cpp @@ -1779,6 +1779,11 @@ void ViewerImpl::update_enabled_entities() } if (!build_reduced) continue; + if (m_settings.reduced_detail_mode == EReducedDetailMode::EndLayersOnly) { + if (whole_layer) + (v.is_option() ? enabled_options_reduced : enabled_segments_reduced).push_back(static_cast(i)); + continue; + } if (!whole_layer && (v.layer_id % layer_stride) != 0) { // the surfaces of a skipped layer that either side can see stay, so that a step does not vanish if (shell_reduced && (visible_from_above || visible_from_below)) diff --git a/src/libvgcode/src/ViewerImpl.hpp b/src/libvgcode/src/ViewerImpl.hpp index c49c25d01b..66ebd14931 100644 --- a/src/libvgcode/src/ViewerImpl.hpp +++ b/src/libvgcode/src/ViewerImpl.hpp @@ -565,7 +565,7 @@ private: bool use_rest_set() const { return !use_reduced_set() && build_rest_set(); } // how many layers each drawn segment of the bound set stands in for float active_height_scale() const { - if (use_reduced_set()) + if (use_reduced_set() && m_settings.reduced_detail_mode != EReducedDetailMode::EndLayersOnly) return static_cast(std::max(1, m_settings.reduced_detail_layer_stride)); if (use_rest_set() && m_settings.rest_detail_mode == EReducedDetailMode::ShellOnly) return static_cast(std::max(1, m_settings.rest_layer_stride)); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index be1bb47683..eb35b912af 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1175,6 +1175,7 @@ void GCodeViewer::load_as_gcode(const GCodeProcessorResult& gcode_result, const // ORCA: simplify the preview while the user is dragging m_reduced_detail_while_dragging = get_app_config()->get_bool("preview_reduced_detail_while_dragging"); m_reduced_detail_mode = reduced_detail_mode_from_string(get_app_config()->get("preview_reduced_detail_mode")); + m_solid_model_while_dragging = m_reduced_detail_mode == libvgcode::EReducedDetailMode::EndLayersOnly; m_reduced_detail_layer_stride = static_cast(std::max(1, std::stoi(get_app_config()->get("preview_reduced_detail_layer_stride")))); m_rest_detail_mode = reduced_detail_mode_from_string(get_app_config()->get("preview_rest_detail_mode")); apply_reduced_detail_settings(); @@ -1653,8 +1654,15 @@ void GCodeViewer::reset() void GCodeViewer::render(int canvas_width, int canvas_height, int right_margin, bool draw_scene) { glsafe(::glEnable(GL_DEPTH_TEST)); - if (draw_scene) - render_shells(canvas_width, canvas_height); + // while dragging in the solid model mode the objects stand in for their toolpaths, cut to the + // visible layer range; the toolpath set then holds only the range's bottom and top layers + const bool solid_model = m_interacting && m_solid_model_while_dragging && m_viewer.is_reduced_detail(); + if (draw_scene) { + if (solid_model) + render_solid_model(canvas_width, canvas_height); + else + render_shells(canvas_width, canvas_height); + } if (m_viewer.get_extrusion_roles_count() == 0) return; @@ -2007,6 +2015,7 @@ void GCodeViewer::set_reduced_detail_while_dragging(bool value) void GCodeViewer::set_reduced_detail_mode(const std::string& mode) { m_reduced_detail_mode = reduced_detail_mode_from_string(mode); + m_solid_model_while_dragging = m_reduced_detail_mode == libvgcode::EReducedDetailMode::EndLayersOnly; apply_reduced_detail_settings(); } @@ -2020,6 +2029,8 @@ libvgcode::EReducedDetailMode GCodeViewer::reduced_detail_mode_from_string(const { if (mode == "full") return libvgcode::EReducedDetailMode::Off; + if (mode == "solid") + return libvgcode::EReducedDetailMode::EndLayersOnly; if (mode == "layers") return libvgcode::EReducedDetailMode::LayersOnly; if (mode == "shell") @@ -2415,6 +2426,19 @@ void GCodeViewer::load_shells(const Print& print, bool initialized, bool force_p object_count++; } + // the prime tower as it was sliced, so that the solid model shows what the print shows; it + // keeps its opaque colour and so never appears among the translucent shells + if (print.is_step_done(psWipeTower) && print.wipe_tower_data().wipe_tower_mesh_data) { + const PrintConfig& config = print.config(); + const int plate_idx = print.get_plate_index(); + const Vec3d plate_origin = print.get_plate_origin(); + const float x = static_cast(config.wipe_tower_x.get_at(plate_idx) + plate_origin.x()); + const float y = static_cast(config.wipe_tower_y.get_at(plate_idx) + plate_origin.y()); + m_shells.volumes.load_real_wipe_tower_preview(1000, x, y, print.wipe_tower_data().wipe_tower_mesh_data->real_wipe_tower_mesh, + print.wipe_tower_data().wipe_tower_mesh_data->real_brim_mesh, true, + static_cast(config.wipe_tower_rotation_angle), false, initialized); + } + // Orca: disable wipe tower shell // if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptFFF) { // // BBS: adds wipe tower's volume @@ -2665,6 +2689,47 @@ void GCodeViewer::render_shells(int canvas_width, int canvas_height) glsafe(::glDepthMask(GL_TRUE)); } +// The sliced objects and the prime tower drawn opaque, in their filament colours, cut to the +// visible layer range by the shader's z range. The toolpaths of the range's bottom and top layers +// are drawn afterwards and cap the cut. +void GCodeViewer::render_solid_model(int canvas_width, int canvas_height) +{ + if (m_shells.volumes.empty()) + return; + GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light"); + if (shader == nullptr) + return; + + const libvgcode::Interval& layers = m_viewer.get_layers_view_range(); + const float z_top = m_viewer.get_layer_z(layers[1]) - m_z_offset + 0.001f; + const float z_bottom = (layers[0] > 0) ? m_viewer.get_layer_z(layers[0] - 1) - m_z_offset - 0.001f : -FLT_MAX; + + std::vector alphas; + alphas.reserve(m_shells.volumes.volumes.size()); + for (GLVolume* volume : m_shells.volumes.volumes) { + alphas.push_back(volume->color.a()); + volume->color.a(1.0f); + volume->set_render_color(); + } + m_shells.volumes.set_z_range(z_bottom, z_top); + + shader->start_using(); + shader->set_uniform("emission_factor", 0.1f); + const Camera& camera = wxGetApp().plater()->get_camera(); + shader->set_uniform("z_far", camera.get_far_z()); + shader->set_uniform("z_near", camera.get_near_z()); + m_shells.volumes.render(GLVolumeCollection::ERenderType::Opaque, false, camera.get_view_matrix(), camera.get_projection_matrix(), {canvas_width, canvas_height}); + shader->set_uniform("emission_factor", 0.0f); + shader->stop_using(); + + m_shells.volumes.set_z_range(-FLT_MAX, FLT_MAX); + size_t k = 0; + for (GLVolume* volume : m_shells.volumes.volumes) { + volume->color.a(alphas[k++]); + volume->set_render_color(); + } +} + //BBS void GCodeViewer::render_all_plates_stats(const std::vector& gcode_result_list, bool show /*= true*/) const { if (!show) diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index d92e4a104a..2849006009 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -235,6 +235,9 @@ private: libvgcode::EReducedDetailMode m_reduced_detail_mode{ libvgcode::EReducedDetailMode::NoInternalInfill }; unsigned int m_reduced_detail_layer_stride{ 4 }; libvgcode::EReducedDetailMode m_rest_detail_mode{ libvgcode::EReducedDetailMode::Off }; + // ORCA: draw the sliced objects as solid shapes instead of toolpaths while dragging + bool m_solid_model_while_dragging{ false }; + void render_solid_model(int canvas_width, int canvas_height); void apply_reduced_detail_settings(); // whether the user is dragging or a wheel burst is settling, as told by set_interacting() bool m_interacting{ false }; diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 6005e3c44f..ad41f7ee4c 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -1977,10 +1977,12 @@ void PreferencesDialog::create_items() "Skip layers only: every toolpath of the drawn layers is kept.\n" "Skip internal infill: sparse and solid infill hidden inside the walls is left out.\n" "Shell only: only the toolpaths on the visible surface of the print are drawn, including the outside of the prime tower. " - "Removes the most, and holes narrower than 5 mm are treated as solid."), + "Removes the most of the toolpath modes, and holes narrower than 5 mm are treated as solid.\n" + "Solid model: the sliced objects and the prime tower are drawn as solid shapes in their filament colours instead of toolpaths, " + "cut to the visible layer range with the range's bottom and top layers drawn on top. Cheapest of all; supports are not shown, and the layer setting below does not apply."), "preview_reduced_detail_mode", - {_L("Skip layers only"), _L("Skip internal infill"), _L("Shell only")}, - {"layers", "no_infill", "shell"}, + {_L("Skip layers only"), _L("Skip internal infill"), _L("Shell only"), _L("Solid model")}, + {"layers", "no_infill", "shell", "solid"}, // ORCA: apply the new mode immediately to the currently loaded preview [](std::string value) { if (Plater* plater = wxGetApp().plater()) {