diff --git a/Build.PL b/Build.PL index 951180135..1e2299632 100644 --- a/Build.PL +++ b/Build.PL @@ -9,7 +9,7 @@ my $build = Module::Build->new( requires => { 'File::Basename' => '0', 'Getopt::Long' => '0', - 'Math::Clipper' => '1.02', + 'Math::Clipper' => '1.03', 'Math::ConvexHull' => '1.0.4', 'Math::Geometry::Voronoi' => '1.3', 'Math::PlanePath' => '53', diff --git a/README.markdown b/README.markdown index 794e97517..1c33decba 100644 --- a/README.markdown +++ b/README.markdown @@ -25,7 +25,8 @@ Slic3r current key features are: * easy configuration/calibration; * read binary and ASCII STL files; * powerful command line interface; -* easy GUI +* easy GUI; +* multithreaded; * multiple infill patterns, with customizable density and angle; * retraction; * skirt; diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index deb894fdc..087a9d0da 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -36,6 +36,8 @@ use Slic3r::Surface; use Slic3r::TriangleMesh; use Slic3r::TriangleMesh::IntersectionLine; +our $threads = 4; + # output options our $output_filename_format = '[input_filename_base].gcode'; diff --git a/lib/Slic3r/Fill.pm b/lib/Slic3r/Fill.pm index b27891668..63c3174a6 100644 --- a/lib/Slic3r/Fill.pm +++ b/lib/Slic3r/Fill.pm @@ -121,6 +121,7 @@ sub make_fill { map [ $_->contour->[0], $_ ], @surfaces, ])}; + my @fills = (); SURFACE: foreach my $surface (@surfaces) { my $filler = $Slic3r::fill_pattern; my $density = $Slic3r::fill_density; @@ -150,7 +151,7 @@ sub make_fill { my $params = shift @paths; # save into layer - push @{ $layer->fills }, Slic3r::ExtrusionPath::Collection->new( + push @fills, Slic3r::ExtrusionPath::Collection->new( paths => [ map Slic3r::ExtrusionPath->new( polyline => Slic3r::Polyline->new(@$_), @@ -163,7 +164,7 @@ sub make_fill { } # add thin fill regions - push @{ $layer->fills }, Slic3r::ExtrusionPath::Collection->new( + push @fills, Slic3r::ExtrusionPath::Collection->new( paths => [ map { $_->isa('Slic3r::Polygon') @@ -172,6 +173,8 @@ sub make_fill { } @{$layer->thin_fills}, ], ) if @{$layer->thin_fills}; + + return @fills; } 1; diff --git a/lib/Slic3r/Skein.pm b/lib/Slic3r/Skein.pm index 15da408e6..f8ad0a199 100644 --- a/lib/Slic3r/Skein.pm +++ b/lib/Slic3r/Skein.pm @@ -1,6 +1,7 @@ package Slic3r::Skein; use Moo; +use Config; use File::Basename qw(basename fileparse); use Slic3r::Geometry qw(PI); use Time::HiRes qw(gettimeofday tv_interval); @@ -84,7 +85,31 @@ sub go { $self->status_cb->(80, "Infilling layers..."); { my $fill_maker = Slic3r::Fill->new('print' => $print); - $fill_maker->make_fill($_) for @{$print->layers}; + + if ($Config{useithreads} && $Slic3r::threads > 1 && eval "use threads; use Thread::Queue; 1") { + my $q = Thread::Queue->new; + $q->enqueue(0..($print->layer_count-1), (map undef, 1..$Slic3r::threads)); + + my $thread_cb = sub { + $Slic3r::Geometry::Clipper::clipper = Math::Clipper->new; + my $fills = {}; + while (defined (my $layer_id = $q->dequeue)) { + $fills->{$layer_id} = [ $fill_maker->make_fill($print->layers->[$layer_id]) ]; + } + return $fills; + }; + + foreach my $th (map threads->create($thread_cb), 1..$Slic3r::threads) { + my $fills = $th->join; + foreach my $layer_id (keys %$fills) { + @{$print->layers->[$layer_id]->fills} = @{$fills->{$layer_id}}; + } + } + } else { + foreach my $layer (@{$print->layers}) { + @{$layer->fills} = $fill_maker->make_fill($layer); + } + } } # output everything to a GCODE file diff --git a/slic3r.pl b/slic3r.pl index d9b6ccc05..9cd944201 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -25,6 +25,7 @@ my %cli_options = (); 'save=s' => \$opt{save}, 'load=s@' => \$opt{load}, 'ignore-nonexistent-config' => \$opt{ignore_nonexistent_config}, + 'threads|j=i' => \$Slic3r::threads, ); foreach my $opt_key (keys %$Slic3r::Config::Options) { my $opt = $Slic3r::Config::Options->{$opt_key};