diff --git a/README.md b/README.md index b981be98f..e117f587d 100644 --- a/README.md +++ b/README.md @@ -253,6 +253,9 @@ The author of the Silk icon set is Mark James. Spacing between pattern lines (mm, default: 2.5) --support-material-angle Support material angle in degrees (range: 0-90, default: 0) + --support-material-contact-distance + Vertical distance between object and support material + (0+, default: 0.2) --support-material-interface-layers Number of perpendicular layers between support material and object (0+, default: 3) --support-material-interface-spacing diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 9d59865a1..b1eb2bcd3 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -453,7 +453,7 @@ sub build { raft_layers support_material_pattern support_material_spacing support_material_angle support_material_interface_layers support_material_interface_spacing - dont_support_bridges + support_material_contact_distance dont_support_bridges notes complete_objects extruder_clearance_radius extruder_clearance_height gcode_comments output_filename_format @@ -556,6 +556,7 @@ sub build { } { my $optgroup = $page->new_optgroup('Options for support material and raft'); + $optgroup->append_single_option_line('support_material_contact_distance'); $optgroup->append_single_option_line('support_material_pattern'); $optgroup->append_single_option_line('support_material_spacing'); $optgroup->append_single_option_line('support_material_angle'); @@ -766,7 +767,7 @@ sub _update { for qw(support_material_threshold support_material_enforce_layers support_material_pattern support_material_spacing support_material_angle support_material_interface_layers dont_support_bridges - support_material_extrusion_width); + support_material_extrusion_width support_material_contact_distance); $self->get_field($_)->toggle($have_support_material && $have_support_interface) for qw(support_material_interface_spacing support_material_interface_extruder support_material_interface_speed); diff --git a/lib/Slic3r/Layer/PerimeterGenerator.pm b/lib/Slic3r/Layer/PerimeterGenerator.pm index 67c758d6e..65950711f 100644 --- a/lib/Slic3r/Layer/PerimeterGenerator.pm +++ b/lib/Slic3r/Layer/PerimeterGenerator.pm @@ -17,6 +17,7 @@ has 'ext_perimeter_flow' => (is => 'ro', required => 1); has 'overhang_flow' => (is => 'ro', required => 1); has 'solid_infill_flow' => (is => 'ro', required => 1); has 'config' => (is => 'ro', default => sub { Slic3r::Config::PrintRegion->new }); +has 'object_config' => (is => 'ro', default => sub { Slic3r::Config::PrintObject->new }); has 'print_config' => (is => 'ro', default => sub { Slic3r::Config::Print->new }); has '_lower_slices_p' => (is => 'rw', default => sub { [] }); has '_holes_pt' => (is => 'rw'); @@ -347,7 +348,8 @@ sub _traverse_loops { # detect overhanging/bridging perimeters my @paths = (); - if ($self->config->overhangs && $self->layer_id > 0) { + if ($self->config->overhangs && $self->layer_id > 0 + && !($self->object_config->support_material && $self->object_config->support_material_contact_distance == 0)) { # get non-overhang paths by intersecting this loop with the grown lower slices foreach my $polyline (@{ intersection_ppl([ $loop->polygon ], $self->_lower_slices_p) }) { push @paths, Slic3r::ExtrusionPath->new( diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm index 88f0db01f..edf56f243 100644 --- a/lib/Slic3r/Layer/Region.pm +++ b/lib/Slic3r/Layer/Region.pm @@ -34,6 +34,7 @@ sub make_perimeters { my $generator = Slic3r::Layer::PerimeterGenerator->new( # input: config => $self->config, + object_config => $self->layer->object->config, print_config => $self->layer->print->config, layer_height => $self->height, layer_id => $self->layer->id, diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index 6211aff33..09f8407f9 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -55,13 +55,14 @@ sub slice { # raise first object layer Z by the thickness of the raft itself # plus the extra distance required by the support material logic - $print_z += $self->config->get_value('first_layer_height'); + my $first_layer_height = $self->config->get_value('first_layer_height'); + $print_z += $first_layer_height; $print_z += $self->config->layer_height * ($self->config->raft_layers - 1); # at this stage we don't know which nozzles are actually used for the first layer # so we compute the average of all of them my $nozzle_diameter = sum(@{$self->print->config->nozzle_diameter})/@{$self->print->config->nozzle_diameter}; - my $distance = Slic3r::Print::SupportMaterial::contact_distance($nozzle_diameter); + my $distance = $self->_support_material->contact_distance($first_layer_height, $nozzle_diameter); # force first layer print_z according to the contact distance # (the loop below will raise print_z by such height) @@ -537,6 +538,14 @@ sub generate_support_material { } $self->print->status_cb->(85, "Generating support material"); + $self->_support_material->generate($self); + + $self->set_step_done(STEP_SUPPORTMATERIAL); +} + +sub _support_material { + my ($self) = @_; + my $first_layer_flow = Slic3r::Flow->new_from_width( width => ($self->config->first_layer_extrusion_width || $self->config->support_material_extrusion_width), role => FLOW_ROLE_SUPPORT_MATERIAL, @@ -546,16 +555,13 @@ sub generate_support_material { bridge_flow_ratio => 0, ); - my $s = Slic3r::Print::SupportMaterial->new( + return Slic3r::Print::SupportMaterial->new( print_config => $self->print->config, object_config => $self->config, first_layer_flow => $first_layer_flow, flow => $self->support_material_flow, interface_flow => $self->support_material_flow(FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE), ); - $s->generate($self); - - $self->set_step_done(STEP_SUPPORTMATERIAL); } sub detect_surfaces_type { @@ -616,6 +622,11 @@ sub detect_surfaces_type { S_TYPE_BOTTOMBRIDGE, ); + # if we have soluble support material, don't bridge + if ($self->config->support_material && $self->config->support_material_contact_distance == 0) { + $_->surface_type(S_TYPE_BOTTOM) for @bottom; + } + # if user requested internal shells, we need to identify surfaces # lying on other slices not belonging to this region if ($self->config->interface_shells) { diff --git a/lib/Slic3r/Print/SupportMaterial.pm b/lib/Slic3r/Print/SupportMaterial.pm index e431f3fb5..6287f3a7e 100644 --- a/lib/Slic3r/Print/SupportMaterial.pm +++ b/lib/Slic3r/Print/SupportMaterial.pm @@ -270,8 +270,7 @@ sub contact_area { @{$layer->regions}; my $nozzle_diameter = sum(@nozzle_diameters)/@nozzle_diameters; - my $contact_z = $layer->print_z - contact_distance($nozzle_diameter); - ###$contact_z = $layer->print_z - $layer->height; + my $contact_z = $layer->print_z - $self->contact_distance($layer->height, $nozzle_diameter); # ignore this contact area if it's too low next if $contact_z < $self->object_config->get_value('first_layer_height'); @@ -339,12 +338,13 @@ sub support_layers_z { # layer_height > nozzle_diameter * 0.75 my $nozzle_diameter = $self->print_config->get_at('nozzle_diameter', $self->object_config->support_material_extruder-1); my $support_material_height = max($max_object_layer_height, $nozzle_diameter * 0.75); + my $contact_distance = $self->contact_distance($support_material_height, $nozzle_diameter); # initialize known, fixed, support layers my @z = sort { $a <=> $b } @$contact_z, @$top_z, # TODO: why we have this? - (map $_ + contact_distance($nozzle_diameter), @$top_z); + (map $_ + $contact_distance, @$top_z); # enforce first layer height my $first_layer_height = $self->object_config->get_value('first_layer_height'); @@ -906,10 +906,15 @@ sub overlapping_layers { } 0..$#$support_z; } -# class method sub contact_distance { - my ($nozzle_diameter) = @_; - return $nozzle_diameter * 1.5; + my ($self, $layer_height, $nozzle_diameter) = @_; + + my $extra = $self->object_config->support_material_contact_distance; + if ($extra == 0) { + return $layer_height; + } else { + return $nozzle_diameter + $extra; + } } 1; diff --git a/slic3r.pl b/slic3r.pl index 3e782ebb5..585d6845b 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -405,6 +405,8 @@ $j Spacing between pattern lines (mm, default: $config->{support_material_spacing}) --support-material-angle Support material angle in degrees (range: 0-90, default: $config->{support_material_angle}) + --support-material-contact-distance + Vertical distance between object and support material (0+, default: $config->{support_material_contact_distance}) --support-material-interface-layers Number of perpendicular layers between support material and object (0+, default: $config->{support_material_interface_layers}) --support-material-interface-spacing diff --git a/t/support.t b/t/support.t index edf5476c5..54d5ef700 100644 --- a/t/support.t +++ b/t/support.t @@ -30,7 +30,7 @@ use Slic3r::Test; first_layer_flow => $flow, ); my $support_z = $support->support_layers_z(\@contact_z, \@top_z, $config->layer_height); - my $expected_top_spacing = Slic3r::Print::SupportMaterial::contact_distance($config->nozzle_diameter->[0]); + my $expected_top_spacing = $support->contact_distance($config->layer_height, $config->nozzle_diameter->[0]); is $support_z->[0], $config->first_layer_height, 'first layer height is honored'; diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index ea585d863..439aef84e 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -780,6 +780,19 @@ PrintConfigDef::build_def() { Options["support_material_angle"].min = 0; Options["support_material_angle"].max = 359; + Options["support_material_contact_distance"].type = coFloat; + Options["support_material_contact_distance"].gui_type = "f_enum_open"; + Options["support_material_contact_distance"].label = "Contact Z distance"; + Options["support_material_contact_distance"].category = "Support material"; + Options["support_material_contact_distance"].tooltip = "The vertical distance between object and support material interface. Setting this to 0 will also prevent Slic3r from using bridge flow and speed for the first object layer."; + Options["support_material_contact_distance"].sidetext = "mm"; + Options["support_material_contact_distance"].cli = "support-material-contact-distance=f"; + Options["support_material_contact_distance"].min = 0; + Options["support_material_contact_distance"].enum_values.push_back("0"); + Options["support_material_contact_distance"].enum_values.push_back("0.2"); + Options["support_material_contact_distance"].enum_labels.push_back("0 (soluble)"); + Options["support_material_contact_distance"].enum_labels.push_back("0.2 (detachable)"); + Options["support_material_enforce_layers"].type = coInt; Options["support_material_enforce_layers"].label = "Enforce support for the first"; Options["support_material_enforce_layers"].category = "Support material"; diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 500babb88..e622f2e95 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -133,6 +133,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig ConfigOptionEnum seam_position; ConfigOptionBool support_material; ConfigOptionInt support_material_angle; + ConfigOptionFloat support_material_contact_distance; ConfigOptionInt support_material_enforce_layers; ConfigOptionInt support_material_extruder; ConfigOptionFloatOrPercent support_material_extrusion_width; @@ -159,6 +160,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig this->seam_position.value = spAligned; this->support_material.value = false; this->support_material_angle.value = 0; + this->support_material_contact_distance.value = 0.2; this->support_material_enforce_layers.value = 0; this->support_material_extruder.value = 1; this->support_material_extrusion_width.value = 0; @@ -186,6 +188,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig if (opt_key == "seam_position") return &this->seam_position; if (opt_key == "support_material") return &this->support_material; if (opt_key == "support_material_angle") return &this->support_material_angle; + if (opt_key == "support_material_contact_distance") return &this->support_material_contact_distance; if (opt_key == "support_material_enforce_layers") return &this->support_material_enforce_layers; if (opt_key == "support_material_extruder") return &this->support_material_extruder; if (opt_key == "support_material_extrusion_width") return &this->support_material_extrusion_width;