More robust fix for 3D view and GUI buttons not in synch when object's size is almost identical to print volume's size
This commit is contained in:
parent
973060c728
commit
71d9500b2e
11 changed files with 33 additions and 76 deletions
|
@ -1396,7 +1396,7 @@ sub Render {
|
||||||
if ($self->enable_picking) {
|
if ($self->enable_picking) {
|
||||||
$self->mark_volumes_for_layer_height;
|
$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->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
|
# do not cull backfaces to show broken geometry, if any
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1921,7 +1921,7 @@ sub object_list_changed {
|
||||||
}
|
}
|
||||||
|
|
||||||
my $export_in_progress = $self->{export_gcode_output_file} || $self->{send_gcode_file};
|
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';
|
my $method = ($have_objects && ! $export_in_progress && $model_fits) ? 'Enable' : 'Disable';
|
||||||
$self->{"btn_$_"}->$method
|
$self->{"btn_$_"}->$method
|
||||||
for grep $self->{"btn_$_"}, qw(reslice export_gcode print send_gcode);
|
for grep $self->{"btn_$_"}, qw(reslice export_gcode print send_gcode);
|
||||||
|
|
|
@ -222,13 +222,14 @@ sub reload_scene {
|
||||||
# checks for geometry outside the print volume to render it accordingly
|
# checks for geometry outside the print volume to render it accordingly
|
||||||
if (scalar @{$self->volumes} > 0)
|
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);
|
$self->set_warning_enabled(1);
|
||||||
Slic3r::GUI::_3DScene::generate_warning_texture(L("Detected object outside print volume"));
|
Slic3r::GUI::_3DScene::generate_warning_texture(L("Detected object outside print volume"));
|
||||||
$self->on_enable_action_buttons->(0) if ($self->on_enable_action_buttons);
|
$self->on_enable_action_buttons->(0) if ($self->on_enable_action_buttons);
|
||||||
} else {
|
} else {
|
||||||
$self->set_warning_enabled(0);
|
$self->set_warning_enabled(0);
|
||||||
$self->volumes->update_outside_state($self->{config}, 1);
|
$self->volumes->reset_outside_state();
|
||||||
Slic3r::GUI::_3DScene::reset_warning_texture();
|
Slic3r::GUI::_3DScene::reset_warning_texture();
|
||||||
$self->on_enable_action_buttons->(1) if ($self->on_enable_action_buttons);
|
$self->on_enable_action_buttons->(1) if ($self->on_enable_action_buttons);
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,31 +147,6 @@ public:
|
||||||
BoundingBoxf3() : BoundingBox3Base<Pointf3>() {};
|
BoundingBoxf3() : BoundingBox3Base<Pointf3>() {};
|
||||||
BoundingBoxf3(const Pointf3 &pmin, const Pointf3 &pmax) : BoundingBox3Base<Pointf3>(pmin, pmax) {};
|
BoundingBoxf3(const Pointf3 &pmin, const Pointf3 &pmax) : BoundingBox3Base<Pointf3>(pmin, pmax) {};
|
||||||
BoundingBoxf3(const std::vector<Pointf3> &points) : BoundingBox3Base<Pointf3>(points) {};
|
BoundingBoxf3(const std::vector<Pointf3> &points) : BoundingBox3Base<Pointf3>(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<typename VT>
|
template<typename VT>
|
||||||
|
|
|
@ -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<const ConfigOptionPoints*>(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 Model::get_auto_extruder_id()
|
||||||
{
|
{
|
||||||
unsigned int id = s_auto_extruder_id;
|
unsigned int id = s_auto_extruder_id;
|
||||||
|
|
|
@ -285,10 +285,6 @@ public:
|
||||||
// Ensures that the min z of the model is not negative
|
// Ensures that the min z of the model is not negative
|
||||||
void adjust_min_z();
|
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(); }
|
void print_info() const { for (const ModelObject *o : this->objects) o->print_info(); }
|
||||||
|
|
||||||
static unsigned int get_auto_extruder_id();
|
static unsigned int get_auto_extruder_id();
|
||||||
|
|
|
@ -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.
|
// 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;
|
print_volume.min.z = -1e10;
|
||||||
for (PrintObject *po : this->objects) {
|
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.";
|
return "Some objects are outside of the print volume.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -643,29 +643,40 @@ void GLVolumeCollection::render_legacy() const
|
||||||
glDisable(GL_BLEND);
|
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)
|
if (config == nullptr)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(config->option("bed_shape"));
|
const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(config->option("bed_shape"));
|
||||||
if (opt == nullptr)
|
if (opt == nullptr)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
|
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")));
|
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
|
// Allow the objects to protrude below the print bed
|
||||||
print_volume.min.z = -1e10;
|
print_volume.min.z = -1e10;
|
||||||
|
|
||||||
|
bool contained = true;
|
||||||
for (GLVolume* volume : this->volumes)
|
for (GLVolume* volume : this->volumes)
|
||||||
{
|
{
|
||||||
if (all_inside)
|
if (volume != nullptr)
|
||||||
{
|
{
|
||||||
volume->is_outside = false;
|
bool state = print_volume.contains(volume->transformed_bounding_box());
|
||||||
continue;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -422,7 +422,9 @@ public:
|
||||||
print_box_max[0] = max_x; print_box_max[1] = max_y; print_box_max[2] = max_z;
|
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);
|
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
|
// Returns a vector containing the sorted list of all the print_zs of the volumes contained in this collection
|
||||||
|
|
|
@ -104,7 +104,12 @@
|
||||||
void release_geometry();
|
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 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);
|
void update_colors_by_extruder(DynamicPrintConfig* config);
|
||||||
|
|
||||||
bool move_volume_up(int idx)
|
bool move_volume_up(int idx)
|
||||||
|
|
|
@ -99,9 +99,6 @@
|
||||||
|
|
||||||
void print_info() const;
|
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)
|
bool store_stl(char *path, bool binary)
|
||||||
%code%{ TriangleMesh mesh = THIS->mesh(); RETVAL = Slic3r::store_stl(path, &mesh, binary); %};
|
%code%{ TriangleMesh mesh = THIS->mesh(); RETVAL = Slic3r::store_stl(path, &mesh, binary); %};
|
||||||
bool store_amf(char *path, Print* print, bool export_print_config)
|
bool store_amf(char *path, Print* print, bool export_print_config)
|
||||||
|
|
Loading…
Reference in a new issue