mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	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) {
 | 
			
		||||
            $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);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -147,31 +147,6 @@ public:
 | 
			
		|||
    BoundingBoxf3() : BoundingBox3Base<Pointf3>() {};
 | 
			
		||||
    BoundingBoxf3(const Pointf3 &pmin, const Pointf3 &pmax) : BoundingBox3Base<Pointf3>(pmin, pmax) {};
 | 
			
		||||
    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>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 id = s_auto_extruder_id;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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.";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<const ConfigOptionPoints*>(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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue