From 4ff13a5d63297438d1c489c40936c4274bb5f562 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 6 Oct 2021 13:47:54 +0200 Subject: [PATCH] Tech ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - Reworked detection of collision with printbed. The detection uses now different algorithms in dependence of the printbed type (rectangular, circular, convex) to improve performance. --- src/libslic3r/GCode/GCodeProcessor.cpp | 16 ++++ src/libslic3r/GCode/GCodeProcessor.hpp | 3 + src/slic3r/GUI/3DBed.cpp | 9 +- src/slic3r/GUI/3DBed.hpp | 1 + src/slic3r/GUI/3DScene.cpp | 115 ++++++++++++++++++------- src/slic3r/GUI/3DScene.hpp | 4 + src/slic3r/GUI/GCodeViewer.cpp | 61 ++++++++++++- src/slic3r/GUI/GCodeViewer.hpp | 11 +++ src/slic3r/GUI/GLCanvas3D.cpp | 59 ++++--------- src/slic3r/GUI/GLCanvas3D.hpp | 4 + 10 files changed, 209 insertions(+), 74 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 9c90535c4..45c0de616 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -720,6 +720,9 @@ void GCodeProcessor::UsedFilaments::process_caches(GCodeProcessor* processor) void GCodeProcessor::Result::reset() { moves = std::vector(); bed_shape = Pointfs(); +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + max_print_height = 0.0f; +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS settings_ids.reset(); extruders_count = 0; extruder_colors = std::vector(); @@ -734,6 +737,9 @@ void GCodeProcessor::Result::reset() { moves.clear(); lines_ends.clear(); bed_shape = Pointfs(); +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + max_print_height = 0.0f; +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS settings_ids.reset(); extruders_count = 0; extruder_colors = std::vector(); @@ -883,6 +889,10 @@ void GCodeProcessor::apply_config(const PrintConfig& config) const ConfigOptionFloatOrPercent* first_layer_height = config.option("first_layer_height"); if (first_layer_height != nullptr) m_first_layer_height = std::abs(first_layer_height->value); + +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + m_result.max_print_height = config.max_print_height; +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS } void GCodeProcessor::apply_config(const DynamicPrintConfig& config) @@ -1112,6 +1122,12 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config) const ConfigOptionFloatOrPercent* first_layer_height = config.option("first_layer_height"); if (first_layer_height != nullptr) m_first_layer_height = std::abs(first_layer_height->value); + +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + const ConfigOptionFloat* max_print_height = config.option("max_print_height"); + if (max_print_height != nullptr) + m_result.max_print_height = max_print_height->value; +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS } void GCodeProcessor::enable_stealth_time_estimator(bool enabled) diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index fce888233..e7d602155 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -351,6 +351,9 @@ namespace Slic3r { // Positions of ends of lines of the final G-code this->filename after TimeProcessor::post_process() finalizes the G-code. std::vector lines_ends; Pointfs bed_shape; +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + float max_print_height; +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS SettingsIds settings_ids; size_t extruders_count; std::vector extruder_colors; diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 6e04664e2..18c017da1 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -282,9 +282,11 @@ bool Bed3D::is_circle(const Pointfs& shape, Vec2d* center, double* radius) avg_dist /= vertex_distances.size(); + double tolerance = avg_dist * 0.01; + bool defined_value = true; for (double el : vertex_distances) { - if (fabs(el - avg_dist) > 10.0 * SCALED_EPSILON) + if (fabs(el - avg_dist) > tolerance) defined_value = false; break; } @@ -298,6 +300,11 @@ bool Bed3D::is_circle(const Pointfs& shape, Vec2d* center, double* radius) return defined_value; } +bool Bed3D::is_convex(const Pointfs& shape) +{ + return Polygon::new_scale(shape).convex_points().size() == shape.size(); +} + Bed3D::EShapeType Bed3D::detect_shape_type(const Pointfs& shape) { if (shape.size() < 3) diff --git a/src/slic3r/GUI/3DBed.hpp b/src/slic3r/GUI/3DBed.hpp index baa0ef5b7..07b9f1758 100644 --- a/src/slic3r/GUI/3DBed.hpp +++ b/src/slic3r/GUI/3DBed.hpp @@ -139,6 +139,7 @@ public: #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS static bool is_rectangle(const Pointfs& shape, Vec2d* min = nullptr, Vec2d* max = nullptr); static bool is_circle(const Pointfs& shape, Vec2d* center = nullptr, double* radius = nullptr); + static bool is_convex(const Pointfs& shape); static EShapeType detect_shape_type(const Pointfs& shape); #endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 3cba38a6e..d6999df61 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -11,6 +11,9 @@ #include "GUI_App.hpp" #include "Plater.hpp" #include "BitmapCache.hpp" +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS +#include "3DBed.hpp" +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #include "libslic3r/ExtrusionEntity.hpp" #include "libslic3r/ExtrusionEntityCollection.hpp" @@ -267,6 +270,12 @@ void GLIndexedVertexArray::render( const std::pair& tverts_range, const std::pair& qverts_range) const { +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + // this method has been called before calling finalize() ? + if (this->vertices_and_normals_interleaved_VBO_id == 0 && !this->vertices_and_normals_interleaved.empty()) + return; +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + assert(this->vertices_and_normals_interleaved_VBO_id != 0); assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0); @@ -879,7 +888,7 @@ int GLVolumeCollection::load_wipe_tower_preview( GLVolume& v = *volumes.back(); v.indexed_vertex_array.load_mesh(mesh); #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - v.calc_convex_hull_3d(); + v.set_convex_hull(mesh.convex_hull_3d()); #endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS v.indexed_vertex_array.finalize_geometry(opengl_initialized); v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0)); @@ -1038,7 +1047,11 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab glsafe(::glDisable(GL_BLEND)); } +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS +bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, ModelInstanceEPrintVolumeState* out_state, bool as_toolpaths) const +#else bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, ModelInstanceEPrintVolumeState* out_state) const +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS { if (config == nullptr) return false; @@ -1050,10 +1063,61 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS const Polygon bed_poly = offset(Polygon::new_scale(opt->values), static_cast(scale_(BedEpsilon))).front(); const float bed_height = config->opt_float("max_print_height"); + const BoundingBox bed_box_2D = get_extents(bed_poly); + BoundingBoxf3 print_volume({ unscale(bed_box_2D.min.x()), unscale(bed_box_2D.min.y()), -1e10 }, + { unscale(bed_box_2D.max.x()), unscale(bed_box_2D.max.y()), bed_height }); + + auto check_against_rectangular_bed = [&print_volume](GLVolume& volume, ModelInstanceEPrintVolumeState& state) { + const BoundingBoxf3* const bb = volume.is_sinking() ? &volume.transformed_non_sinking_bounding_box() : &volume.transformed_convex_hull_bounding_box(); + volume.is_outside = !print_volume.contains(*bb); + if (volume.printable) { + if (state == ModelInstancePVS_Inside && volume.is_outside) + state = ModelInstancePVS_Fully_Outside; + if (state == ModelInstancePVS_Fully_Outside && volume.is_outside && print_volume.intersects(*bb)) + state = ModelInstancePVS_Partly_Outside; + } + }; + + auto check_against_circular_bed = [](GLVolume& volume, ModelInstanceEPrintVolumeState& state, const Vec2d& center, double radius) { + const TriangleMesh* mesh = volume.is_sinking() ? &GUI::wxGetApp().plater()->model().objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh() : volume.convex_hull(); + const Polygon volume_hull_2d = its_convex_hull_2d_above(mesh->its, volume.world_matrix().cast(), 0.0f); + size_t outside_count = 0; + const double sq_radius = sqr(radius); + for (const Point& p : volume_hull_2d.points) { + if (sq_radius < (unscale(p) - center).squaredNorm()) + ++outside_count; + } + + volume.is_outside = outside_count > 0; + if (volume.printable) { + if (state == ModelInstancePVS_Inside && volume.is_outside) + state = ModelInstancePVS_Fully_Outside; + if (state == ModelInstancePVS_Fully_Outside && volume.is_outside && outside_count < volume_hull_2d.size()) + state = ModelInstancePVS_Partly_Outside; + } + }; + + auto check_against_convex_bed = [&bed_poly, bed_height](GLVolume& volume, ModelInstanceEPrintVolumeState& state) { + const TriangleMesh* mesh = volume.is_sinking() ? &GUI::wxGetApp().plater()->model().objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh() : volume.convex_hull(); + const Polygon volume_hull_2d = its_convex_hull_2d_above(mesh->its, volume.world_matrix().cast(), 0.0f); + const BoundingBoxf3* const bb = volume.is_sinking() ? &volume.transformed_non_sinking_bounding_box() : &volume.transformed_convex_hull_bounding_box(); + ModelInstanceEPrintVolumeState volume_state = printbed_collision_state(bed_poly, bed_height, volume_hull_2d, bb->min.z(), bb->max.z()); + bool contained = (volume_state == ModelInstancePVS_Inside); + bool intersects = (volume_state == ModelInstancePVS_Partly_Outside); + + volume.is_outside = !contained; + if (volume.printable) { + if (state == ModelInstancePVS_Inside && volume.is_outside) + state = ModelInstancePVS_Fully_Outside; + + if (state == ModelInstancePVS_Fully_Outside && volume.is_outside && intersects) + state = ModelInstancePVS_Partly_Outside; + } + }; #else const BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values)); - BoundingBoxf3 print_volume({ unscale(bed_box_2D.min.x()), unscale(bed_box_2D.min.y()), 0.0 }, - { unscale(bed_box_2D.max.x()), unscale(bed_box_2D.max.y()), config->opt_float("max_print_height") }); + BoundingBoxf3 print_volume({ unscale(bed_box_2D.min.x()), unscale(bed_box_2D.min.y()), 0.0 }, + { unscale(bed_box_2D.max.x()), unscale(bed_box_2D.max.y()), config->opt_float("max_print_height") }); // Allow the objects to protrude below the print bed print_volume.min.z() = -1e10; print_volume.min.x() -= BedEpsilon; @@ -1063,36 +1127,33 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M #endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Inside; - bool contained_min_one = false; for (GLVolume* volume : this->volumes) { +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + if (as_toolpaths && !volume->is_extrusion_path) + continue; + else if (!as_toolpaths && (volume->is_modifier || (!volume->shader_outside_printer_detection_enabled && (volume->is_wipe_tower || volume->composite_id.volume_id < 0)))) + continue; + + if (GUI::Bed3D::is_rectangle(opt->values)) + check_against_rectangular_bed(*volume, overall_state); + else { + Vec2d center; + double radius; + if (GUI::Bed3D::is_circle(opt->values, ¢er, &radius)) + check_against_circular_bed(*volume, overall_state, center, radius); + else if (GUI::Bed3D::is_convex(opt->values)) + check_against_convex_bed(*volume, overall_state); + } + + contained_min_one |= !volume->is_outside; +#else if (volume->is_modifier || (!volume->shader_outside_printer_detection_enabled && (volume->is_wipe_tower || volume->composite_id.volume_id < 0))) continue; -#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - bool contained = false; - bool intersects = false; - bool is_aux_volume = volume->is_sla_support() || volume->is_sla_pad() || volume->is_wipe_tower; - const BoundingBoxf3 bb = is_aux_volume ? volume->transformed_convex_hull_bounding_box() : volume->transformed_non_sinking_bounding_box(); - ModelInstanceEPrintVolumeState volume_state; - if (is_aux_volume) { - if (volume->is_sla_support() || volume->is_wipe_tower) { - const Polygon volume_hull_2d = its_convex_hull_2d_above(volume->convex_hull()->its, volume->world_matrix().cast(), 0.0f); - volume_state = printbed_collision_state(bed_poly, bed_height, volume_hull_2d, bb.min.z(), bb.max.z()); - } - } - else { - const TriangleMesh* mesh = volume->is_sinking() ? &GUI::wxGetApp().plater()->model().objects[volume->object_idx()]->volumes[volume->volume_idx()]->mesh() : volume->convex_hull(); - const Polygon volume_hull_2d = its_convex_hull_2d_above(mesh->its, volume->world_matrix().cast(), 0.0f); - volume_state = printbed_collision_state(bed_poly, bed_height, volume_hull_2d, bb.min.z(), bb.max.z()); - } - contained = (volume_state == ModelInstancePVS_Inside); - intersects = (volume_state == ModelInstancePVS_Partly_Outside); -#else const BoundingBoxf3& bb = volume->transformed_convex_hull_bounding_box(); bool contained = print_volume.contains(bb); -#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS volume->is_outside = !contained; if (!volume->printable) @@ -1103,10 +1164,6 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M if (overall_state == ModelInstancePVS_Inside && volume->is_outside) overall_state = ModelInstancePVS_Fully_Outside; -#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - if (overall_state == ModelInstancePVS_Fully_Outside && volume->is_outside && intersects) - overall_state = ModelInstancePVS_Partly_Outside; -#else if (overall_state == ModelInstancePVS_Fully_Outside && volume->is_outside && print_volume.intersects(bb)) overall_state = ModelInstancePVS_Partly_Outside; #endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index 0b1293f56..14597f22a 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -654,7 +654,11 @@ public: // returns true if all the volumes are completely contained in the print volume // returns the containment state in the given out_state, if non-null +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + bool check_outside_state(const DynamicPrintConfig* config, ModelInstanceEPrintVolumeState* out_state, bool as_toolpaths = false) const; +#else bool check_outside_state(const DynamicPrintConfig* config, ModelInstanceEPrintVolumeState* out_state) const; +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS void reset_outside_state(); void update_colors_by_extruder(const DynamicPrintConfig* config); diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index fd2fe9cbc..00fa066c9 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -6,10 +6,11 @@ #include "libslic3r/Model.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/LocalesUtils.hpp" +#include "libslic3r/PresetBundle.hpp" + #include "GUI_App.hpp" #include "MainFrame.hpp" #include "Plater.hpp" -#include "libslic3r/PresetBundle.hpp" #include "Camera.hpp" #include "I18N.hpp" #include "GUI_Utils.hpp" @@ -19,6 +20,10 @@ #include "GLToolbar.hpp" #include "GUI_Preview.hpp" #include "GUI_ObjectManipulation.hpp" +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS +#include "3DBed.hpp" +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + #include #include @@ -674,6 +679,10 @@ void GCodeViewer::load(const GCodeProcessor::Result& gcode_result, const Print& if (wxGetApp().is_gcode_viewer()) m_custom_gcode_per_print_z = gcode_result.custom_gcode_per_print_z; +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + m_max_print_height = gcode_result.max_print_height; +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + load_toolpaths(gcode_result); if (m_layers.empty()) @@ -819,6 +828,9 @@ void GCodeViewer::reset() m_paths_bounding_box = BoundingBoxf3(); m_max_bounding_box = BoundingBoxf3(); +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + m_max_print_height = 0.0f; +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS m_tool_colors = std::vector(); m_extruders_count = 0; m_extruder_ids = std::vector(); @@ -835,6 +847,9 @@ void GCodeViewer::reset() #if ENABLE_GCODE_VIEWER_STATISTICS m_statistics.reset_all(); #endif // ENABLE_GCODE_VIEWER_STATISTICS +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + m_contained_in_bed = true; +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS } void GCodeViewer::render() @@ -1554,7 +1569,49 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // set approximate max bounding box (take in account also the tool marker) m_max_bounding_box = m_paths_bounding_box; - m_max_bounding_box.merge(m_paths_bounding_box.max + m_sequential_view.marker.get_bounding_box().size()[2] * Vec3d::UnitZ()); + m_max_bounding_box.merge(m_paths_bounding_box.max + m_sequential_view.marker.get_bounding_box().size().z() * Vec3d::UnitZ()); + +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + if (wxGetApp().is_editor()) { + const Bed3D::EShapeType bed_type = wxGetApp().plater()->get_bed().get_shape_type(); + if (bed_type == Bed3D::EShapeType::Rectangle) { + BoundingBoxf3 print_volume = wxGetApp().plater()->get_bed().get_bounding_box(false); + print_volume.min.z() = -1e10; + print_volume.max.z() = m_max_print_height; + print_volume.min -= Vec3f(BedEpsilon, BedEpsilon, 0.0f).cast(); + print_volume.max += Vec3f(BedEpsilon, BedEpsilon, 0.0f).cast(); + m_contained_in_bed = print_volume.contains(m_paths_bounding_box); + } + else if (bed_type == Bed3D::EShapeType::Circle) { + Vec2d center; + double radius; + Bed3D::is_circle(wxGetApp().plater()->get_bed().get_shape(), ¢er, &radius); + const double sq_radius = sqr(radius); + for (const GCodeProcessor::MoveVertex& move : gcode_result.moves) { + if (move.type == EMoveType::Extrude && move.extrusion_role != erCustom && move.width != 0.0f && move.height != 0.0f) { + if (sq_radius < (Vec2d(move.position.x(), move.position.y()) - center).squaredNorm()) { + m_contained_in_bed = false; + break; + } + } + } + } + else if (bed_type == Bed3D::EShapeType::Custom) { + const Pointfs& shape = wxGetApp().plater()->get_bed().get_shape(); + if (Bed3D::is_convex(shape)) { + const Polygon poly = Polygon::new_scale(shape); + for (const GCodeProcessor::MoveVertex& move : gcode_result.moves) { + if (move.type == EMoveType::Extrude && move.extrusion_role != erCustom && move.width != 0.0f && move.height != 0.0f) { + if (!poly.contains(Point::new_scale(Vec2d(move.position.x(), move.position.y())))) { + m_contained_in_bed = false; + break; + } + } + } + } + } + } +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #if ENABLE_FIX_SEAMS_SYNCH m_sequential_view.gcode_ids.clear(); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 1b5a53f9d..66fcba2bc 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -780,6 +780,9 @@ private: BoundingBoxf3 m_paths_bounding_box; // bounding box of toolpaths + marker tools BoundingBoxf3 m_max_bounding_box; +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + float m_max_print_height{ 0.0f }; +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS std::vector m_tool_colors; Layers m_layers; std::array m_layers_z_range; @@ -804,6 +807,10 @@ private: std::vector m_custom_gcode_per_print_z; +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + bool m_contained_in_bed{ true }; +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + public: GCodeViewer(); ~GCodeViewer() { reset(); } @@ -832,6 +839,10 @@ public: const SequentialView& get_sequential_view() const { return m_sequential_view; } void update_sequential_view_current(unsigned int first, unsigned int last); +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + bool is_contained_in_bed() const { return m_contained_in_bed; } +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + EViewType get_view_type() const { return m_view_type; } void set_view_type(EViewType type) { if (type == EViewType::Count) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 2cc92f987..2d8c2f9bd 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1108,10 +1108,18 @@ void GLCanvas3D::reset_volumes() _set_warning_notification(EWarning::ObjectOutside, false); } +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS +ModelInstanceEPrintVolumeState GLCanvas3D::check_volumes_outside_state(bool as_toolpaths) const +#else ModelInstanceEPrintVolumeState GLCanvas3D::check_volumes_outside_state() const +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS { ModelInstanceEPrintVolumeState state; +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + m_volumes.check_outside_state(m_config, &state, as_toolpaths); +#else m_volumes.check_outside_state(m_config, &state); +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS return state; } @@ -5016,24 +5024,16 @@ void GLCanvas3D::_render_background() const if (!m_volumes.empty()) use_error_color &= _is_any_volume_outside(); - else { + else #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - ModelInstanceEPrintVolumeState state; - if (m_gcode_viewer.has_data()) { - const Polygon bed_poly = offset(Polygon::new_scale(wxGetApp().plater()->get_bed().get_shape()), static_cast(scale_(BedEpsilon))).front(); - const float bed_height = m_config->opt_float("max_print_height"); - state = printbed_collision_state(bed_poly, bed_height, m_gcode_viewer.get_paths_bounding_box()); - } - else - state = ModelInstancePVS_Inside; - - use_error_color &= state != ModelInstancePVS_Inside; + use_error_color &= m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed(); #else + { const BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3(); const BoundingBoxf3& paths_volume = m_gcode_viewer.get_paths_bounding_box(); use_error_color &= (test_volume.radius() > 0.0 && paths_volume.radius() > 0.0) ? !test_volume.contains(paths_volume) : false; -#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS } +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS } glsafe(::glPushMatrix()); @@ -6379,18 +6379,7 @@ void GLCanvas3D::_load_sla_shells() void GLCanvas3D::_update_toolpath_volumes_outside_state() { #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - const Polygon bed_poly = offset(Polygon::new_scale(wxGetApp().plater()->get_bed().get_shape()), static_cast(scale_(BedEpsilon))).front(); - const float bed_height = m_config->opt_float("max_print_height"); - for (GLVolume* volume : m_volumes.volumes) { - if (volume->is_extrusion_path) { - const BoundingBoxf3& bb = volume->transformed_convex_hull_bounding_box(); - const Polygon volume_hull_2d = its_convex_hull_2d_above(volume->convex_hull()->its, volume->world_matrix().cast(), 0.0f); - const ModelInstanceEPrintVolumeState state = printbed_collision_state(bed_poly, bed_height, volume_hull_2d, bb.min.z(), bb.max.z()); - volume->is_outside = (state != ModelInstancePVS_Inside); - } - else - volume->is_outside = false; - } + check_volumes_outside_state(true); #else BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3(); for (GLVolume* volume : m_volumes.volumes) { @@ -6402,18 +6391,7 @@ void GLCanvas3D::_update_toolpath_volumes_outside_state() void GLCanvas3D::_update_sla_shells_outside_state() { #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - const Polygon bed_poly = offset(Polygon::new_scale(wxGetApp().plater()->get_bed().get_shape()), static_cast(scale_(BedEpsilon))).front(); - const float bed_height = m_config->opt_float("max_print_height"); - for (GLVolume* volume : m_volumes.volumes) { - if (volume->shader_outside_printer_detection_enabled) { - const BoundingBoxf3& bb = volume->transformed_convex_hull_bounding_box(); - const Polygon volume_hull_2d = its_convex_hull_2d_above(volume->convex_hull()->its, volume->world_matrix().cast(), 0.0f); - const ModelInstanceEPrintVolumeState state = printbed_collision_state(bed_poly, bed_height, volume_hull_2d, bb.min.z(), bb.max.z()); - volume->is_outside = (state != ModelInstancePVS_Inside); - } - else - volume->is_outside = false; - } + check_volumes_outside_state(); #else BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3(); for (GLVolume* volume : m_volumes.volumes) { @@ -6431,12 +6409,8 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning) else { if (wxGetApp().is_editor()) { #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - if (current_printer_technology() != ptSLA) { - const Polygon bed_poly = offset(Polygon::new_scale(wxGetApp().plater()->get_bed().get_shape()), static_cast(scale_(BedEpsilon))).front(); - const float bed_height = m_config->opt_float("max_print_height"); - const ModelInstanceEPrintVolumeState state = printbed_collision_state(bed_poly, bed_height, m_gcode_viewer.get_paths_bounding_box()); - show = state != ModelInstancePVS_Inside; - } + if (current_printer_technology() != ptSLA) + show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed(); #else BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3(); const BoundingBoxf3& paths_volume = m_gcode_viewer.get_paths_bounding_box(); @@ -6445,6 +6419,7 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning) #endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS } } + _set_warning_notification(warning, show); } diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index beb33c89b..d3c24694c 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -621,7 +621,11 @@ public: unsigned int get_volumes_count() const; const GLVolumeCollection& get_volumes() const { return m_volumes; } void reset_volumes(); +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + ModelInstanceEPrintVolumeState check_volumes_outside_state(bool as_toolpaths = false) const; +#else ModelInstanceEPrintVolumeState check_volumes_outside_state() const; +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #if ENABLE_SEAMS_USING_MODELS void init_gcode_viewer() { m_gcode_viewer.init(); }