diff --git a/lib/Slic3r/GUI/3DScene.pm b/lib/Slic3r/GUI/3DScene.pm index ff6d73399..80fa337c4 100644 --- a/lib/Slic3r/GUI/3DScene.pm +++ b/lib/Slic3r/GUI/3DScene.pm @@ -1396,7 +1396,7 @@ sub Render { if ($self->enable_picking) { $self->mark_volumes_for_layer_height; $self->volumes->set_print_box($self->bed_bounding_box->x_min, $self->bed_bounding_box->y_min, 0.0, $self->bed_bounding_box->x_max, $self->bed_bounding_box->y_max, $self->{config}->get('max_print_height')); - $self->volumes->update_outside_state($self->{config}, 0); + $self->volumes->check_outside_state($self->{config}); # do not cull backfaces to show broken geometry, if any glDisable(GL_CULL_FACE); } diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index ce78eab8e..f9ce75eff 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1921,7 +1921,7 @@ sub object_list_changed { } my $export_in_progress = $self->{export_gcode_output_file} || $self->{send_gcode_file}; - my $model_fits = $self->{model}->fits_print_volume($self->{config}); + my $model_fits = $self->{canvas3D} ? $self->{canvas3D}->volumes->check_outside_state($self->{config}) : 1; my $method = ($have_objects && ! $export_in_progress && $model_fits) ? 'Enable' : 'Disable'; $self->{"btn_$_"}->$method for grep $self->{"btn_$_"}, qw(reslice export_gcode print send_gcode); diff --git a/lib/Slic3r/GUI/Plater/3D.pm b/lib/Slic3r/GUI/Plater/3D.pm index dce60e2c4..54b916773 100644 --- a/lib/Slic3r/GUI/Plater/3D.pm +++ b/lib/Slic3r/GUI/Plater/3D.pm @@ -222,13 +222,14 @@ sub reload_scene { # checks for geometry outside the print volume to render it accordingly if (scalar @{$self->volumes} > 0) { - if (!$self->{model}->fits_print_volume($self->{config})) { + my $contained = $self->volumes->check_outside_state($self->{config}); + if (!$contained) { $self->set_warning_enabled(1); Slic3r::GUI::_3DScene::generate_warning_texture(L("Detected object outside print volume")); $self->on_enable_action_buttons->(0) if ($self->on_enable_action_buttons); } else { $self->set_warning_enabled(0); - $self->volumes->update_outside_state($self->{config}, 1); + $self->volumes->reset_outside_state(); Slic3r::GUI::_3DScene::reset_warning_texture(); $self->on_enable_action_buttons->(1) if ($self->on_enable_action_buttons); } diff --git a/xs/src/libslic3r/BoundingBox.hpp b/xs/src/libslic3r/BoundingBox.hpp index a96fd1a30..92a2bd451 100644 --- a/xs/src/libslic3r/BoundingBox.hpp +++ b/xs/src/libslic3r/BoundingBox.hpp @@ -147,31 +147,6 @@ public: BoundingBoxf3() : BoundingBox3Base() {}; BoundingBoxf3(const Pointf3 &pmin, const Pointf3 &pmax) : BoundingBox3Base(pmin, pmax) {}; BoundingBoxf3(const std::vector &points) : BoundingBox3Base(points) {}; - - // check if the given point is contained inside this bounding box - // all quantities are compared after being quantized to try to reduce instability due to float imprecision - bool contains_quantized(const Pointf3& point) const { - struct Helper - { - static coordf_t quantize(coordf_t value) - { - static const coordf_t INV_EPSILON = 1.0 / EPSILON; - return round(value * INV_EPSILON + 0.5) * EPSILON; - } - }; - - coordf_t x = Helper::quantize(point.x); - coordf_t y = Helper::quantize(point.y); - coordf_t z = Helper::quantize(point.z); - - return (Helper::quantize(min.x) <= x) && (x <= Helper::quantize(max.x)) - && (Helper::quantize(min.y) <= y) && (y <= Helper::quantize(max.y)) - && (Helper::quantize(min.z) <= z) && (z <= Helper::quantize(max.z)); - } - - bool contains_quantized(const BoundingBoxf3& other) const { - return contains_quantized(other.min) && contains_quantized(other.max); - } }; template diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index 25e207304..9c9b56659 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -447,36 +447,6 @@ void Model::adjust_min_z() } } -bool Model::fits_print_volume(const DynamicPrintConfig* config) const -{ - if (config == nullptr) - return false; - - if (objects.empty()) - return true; - - const ConfigOptionPoints* opt = dynamic_cast(config->option("bed_shape")); - if (opt == nullptr) - return false; - - BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values)); - BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(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; - return print_volume.contains_quantized(transformed_bounding_box()); -} - -bool Model::fits_print_volume(const FullPrintConfig &config) const -{ - if (objects.empty()) - return true; - BoundingBox bed_box_2D = get_extents(Polygon::new_scale(config.bed_shape.values)); - BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config.max_print_height)); - // Allow the objects to protrude below the print bed - print_volume.min.z = -1e10; - return print_volume.contains_quantized(transformed_bounding_box()); -} - unsigned int Model::get_auto_extruder_id() { unsigned int id = s_auto_extruder_id; diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index 0c0ffe776..0baea979c 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -285,10 +285,6 @@ public: // Ensures that the min z of the model is not negative void adjust_min_z(); - // Returs true if this model is contained into the print volume defined inside the given config - bool fits_print_volume(const DynamicPrintConfig* config) const; - bool fits_print_volume(const FullPrintConfig &config) const; - void print_info() const { for (const ModelObject *o : this->objects) o->print_info(); } static unsigned int get_auto_extruder_id(); diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 9de5c0379..585977ba7 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -522,7 +522,7 @@ std::string Print::validate() const // Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced. print_volume.min.z = -1e10; for (PrintObject *po : this->objects) { - if (!print_volume.contains_quantized(po->model_object()->tight_bounding_box(false))) + if (!print_volume.contains(po->model_object()->tight_bounding_box(false))) return "Some objects are outside of the print volume."; } diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp index 7d4e4d68c..b9ac1966e 100644 --- a/xs/src/slic3r/GUI/3DScene.cpp +++ b/xs/src/slic3r/GUI/3DScene.cpp @@ -643,29 +643,40 @@ void GLVolumeCollection::render_legacy() const glDisable(GL_BLEND); } -void GLVolumeCollection::update_outside_state(const DynamicPrintConfig* config, bool all_inside) +bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config) { if (config == nullptr) - return; + return false; const ConfigOptionPoints* opt = dynamic_cast(config->option("bed_shape")); if (opt == nullptr) - return; + return false; BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values)); BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(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; + bool contained = true; for (GLVolume* volume : this->volumes) { - if (all_inside) + if (volume != nullptr) { - volume->is_outside = false; - continue; + bool state = print_volume.contains(volume->transformed_bounding_box()); + contained &= state; + volume->is_outside = !state; } + } - volume->is_outside = !print_volume.contains_quantized(volume->transformed_bounding_box()); + return contained; +} + +void GLVolumeCollection::reset_outside_state() +{ + for (GLVolume* volume : this->volumes) + { + if (volume != nullptr) + volume->is_outside = false; } } diff --git a/xs/src/slic3r/GUI/3DScene.hpp b/xs/src/slic3r/GUI/3DScene.hpp index 8f03e4774..fb5d9f14b 100644 --- a/xs/src/slic3r/GUI/3DScene.hpp +++ b/xs/src/slic3r/GUI/3DScene.hpp @@ -422,7 +422,9 @@ public: print_box_max[0] = max_x; print_box_max[1] = max_y; print_box_max[2] = max_z; } - void update_outside_state(const DynamicPrintConfig* config, bool all_inside); + bool check_outside_state(const DynamicPrintConfig* config); + void reset_outside_state(); + void update_colors_by_extruder(const DynamicPrintConfig* config); // Returns a vector containing the sorted list of all the print_zs of the volumes contained in this collection diff --git a/xs/xsp/GUI_3DScene.xsp b/xs/xsp/GUI_3DScene.xsp index 86d0aeba2..ee5a82ba1 100644 --- a/xs/xsp/GUI_3DScene.xsp +++ b/xs/xsp/GUI_3DScene.xsp @@ -104,7 +104,12 @@ void release_geometry(); void set_print_box(float min_x, float min_y, float min_z, float max_x, float max_y, float max_z); - void update_outside_state(DynamicPrintConfig* config, bool all_inside); + bool check_outside_state(DynamicPrintConfig* config) + %code%{ + RETVAL = THIS->check_outside_state(config); + %}; + + void reset_outside_state(); void update_colors_by_extruder(DynamicPrintConfig* config); bool move_volume_up(int idx) diff --git a/xs/xsp/Model.xsp b/xs/xsp/Model.xsp index 702839537..02017839a 100644 --- a/xs/xsp/Model.xsp +++ b/xs/xsp/Model.xsp @@ -99,9 +99,6 @@ void print_info() const; - bool fits_print_volume(DynamicPrintConfig* config) const - %code%{ RETVAL = THIS->fits_print_volume(config); %}; - bool store_stl(char *path, bool binary) %code%{ TriangleMesh mesh = THIS->mesh(); RETVAL = Slic3r::store_stl(path, &mesh, binary); %}; bool store_amf(char *path, Print* print, bool export_print_config)