diff --git a/lib/Slic3r/Layer.pm b/lib/Slic3r/Layer.pm index 43d014490..e99b44ba9 100644 --- a/lib/Slic3r/Layer.pm +++ b/lib/Slic3r/Layer.pm @@ -14,7 +14,7 @@ has 'flow' => (is => 'lazy'); has 'perimeter_flow' => (is => 'lazy'); has 'infill_flow' => (is => 'lazy'); -# collection of surfaces generated by slicing the original geometry; +# collection of expolygons generated by slicing the original geometry; # also known as 'islands' (all materials are merged here) has 'slices' => (is => 'rw'); @@ -68,8 +68,8 @@ sub material { my $self = shift; my ($material_idx) = @_; - for my $i (grep !defined $self->materials->[$_], 0..$material_idx) { - $self->materials->[$i] = Slic3r::Layer::Material->new( + if (!defined $self->materials->[$material_idx]) { + $self->materials->[$material_idx] = Slic3r::Layer::Material->new( layer => $self, ); } @@ -83,11 +83,11 @@ sub make_slices { # optimization for single-material layers my @materials_with_slices = grep { @{$_->slices} } @{$self->materials}; if (@materials_with_slices == 1) { - $self->slices($materials_with_slices[0]->slices); + $self->slices([ map $_->expolygon, @{$materials_with_slices[0]->slices} ]); return; } - $self->slices(union_ex([ map @{$_->slices}, @{$self->materials} ])); + $self->slices(union_ex([ map $_->p, map @{$_->slices}, @{$self->materials} ])); } sub make_perimeters { diff --git a/lib/Slic3r/Layer/Material.pm b/lib/Slic3r/Layer/Material.pm index 746d8c320..924a1fc8c 100644 --- a/lib/Slic3r/Layer/Material.pm +++ b/lib/Slic3r/Layer/Material.pm @@ -19,36 +19,37 @@ has 'layer' => ( has 'lines' => (is => 'rw', default => sub { [] }); # collection of surfaces generated by slicing the original geometry -has 'slices' => (is => 'rw'); +has 'slices' => (is => 'rw', default => sub { [] }); # collection of polygons or polylines representing thin walls contained # in the original geometry -has 'thin_walls' => (is => 'rw'); +has 'thin_walls' => (is => 'rw', default => sub { [] }); # collection of polygons or polylines representing thin infill regions that # need to be filled with a medial axis -has 'thin_fills' => (is => 'rw'); +has 'thin_fills' => (is => 'rw', default => sub { [] }); # collection of expolygons generated by offsetting the innermost perimeter(s) # they represent boundaries of areas to fill, typed (top/bottom/internal) -has 'surfaces' => (is => 'rw'); +has 'surfaces' => (is => 'rw', default => sub { [] }); # collection of surfaces for infill generation. the difference between surfaces # fill_surfaces is that this one honors fill_density == 0 and turns small internal # surfaces into solid ones -has 'fill_surfaces' => (is => 'rw'); +has 'fill_surfaces' => (is => 'rw', default => sub { [] }); # ordered collection of extrusion paths/loops to build all perimeters -has 'perimeters' => (is => 'rw'); +has 'perimeters' => (is => 'rw', default => sub { [] }); # ordered collection of extrusion paths to fill surfaces -has 'fills' => (is => 'rw'); +has 'fills' => (is => 'rw', default => sub { [] }); # build polylines from lines sub make_surfaces { my $self = shift; my ($loops) = @_; + return if !@$loops; { my $safety_offset = scale 0.1; # merge everything diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index c131dbc4a..eae844b5a 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -97,9 +97,10 @@ sub add_model { foreach my $volume (@{$object->volumes}) { # should the object contain multiple volumes of the same material, merge them my $material_id = $volume->material_id // 0; #/ + my $mesh = $volume->mesh->clone; $meshes[$material_id] = $meshes[$material_id] - ? Slic3r::TriangleMesh->merge($meshes[$material_id], $volume->mesh) - : $volume->mesh; + ? Slic3r::TriangleMesh->merge($meshes[$material_id], $mesh) + : $mesh; } foreach my $mesh (@meshes) { @@ -281,10 +282,10 @@ sub export_gcode { # simplify slices (both layer and material slices), # we only need the max resolution for perimeters - $_->simplify(scale &Slic3r::RESOLUTION) - for map @{$_->expolygon}, - map { my $layer = $_; ((map @{$_->slices}, @{$layer->materials}), @{$layer->slices}) } - map @{$_->layers}, @{$self->objects}; + foreach my $layer (map @{$_->layers}, @{$self->objects}) { + $_->simplify(scale &Slic3r::RESOLUTION) + for @{$layer->slices}, (map $_->expolygon, map @{$_->slices}, @{$layer->materials}); + } # this will clip $layer->surfaces to the infill boundaries # and split them in top/bottom/internal surfaces; @@ -494,7 +495,7 @@ sub make_skirt { foreach my $obj_idx (0 .. $#{$self->objects}) { my @layers = map $self->objects->[$obj_idx]->layer($_), 0..($skirt_height-1); my @layer_points = ( - (map @$_, map @{$_->expolygon}, map @{$_->slices}, @layers), + (map @$_, map @$_, map @{$_->slices}, @layers), (map @$_, map @{$_->thin_walls}, map @{$_->materials}, @layers), (map @{$_->unpack->polyline}, map @{$_->support_fills->paths}, grep $_->support_fills, @layers), ); diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index c1319fd45..9cedc3a7d 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -84,6 +84,9 @@ sub slice { pop @{$self->layers} if !map @{$_->lines}, @{$self->layers->[-1]->materials}; foreach my $layer (@{ $self->layers }) { + # make sure all layers contain layer material objects for all materials + $layer->material($_) for 0 .. ($self->print->materials_count-1); + Slic3r::debugf "Making surfaces for layer %d (slice z = %f):\n", $layer->id, unscale $layer->slice_z if $Slic3r::debug;