From 68b48fa807de50d6d05078e411b3b5fb3e51a3e4 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 9 Apr 2012 12:29:47 +0200 Subject: [PATCH] Multithreaded mesh processing. #154 --- lib/Slic3r.pm | 17 +++++++++++++++++ lib/Slic3r/Print.pm | 35 ++++++++++++++++++++++++++++++++++- lib/Slic3r/TriangleMesh.pm | 5 ++++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm index 5c5e3b06..7a372acc 100644 --- a/lib/Slic3r.pm +++ b/lib/Slic3r.pm @@ -14,6 +14,7 @@ sub debugf { printf @_ if $debug; } +use Config; use Slic3r::Config; use Slic3r::ExPolygon; use Slic3r::Extruder; @@ -141,4 +142,20 @@ our $duplicate_x = 1; our $duplicate_y = 1; our $duplicate_distance = 6; # mm +sub parallelize { + my %params = @_; + + if (!$params{disable} && $Config{useithreads} && $Slic3r::threads > 1 && eval "use threads; use Thread::Queue; 1") { + my $q = Thread::Queue->new; + $q->enqueue(@{ $params{items} }, (map undef, 1..$Slic3r::threads)); + + my $thread_cb = sub { $params{thread_cb}->($q) }; + foreach my $th (map threads->create($thread_cb), 1..$Slic3r::threads) { + $params{collect_cb}->($th->join); + } + } else { + $params{no_threads_cb}->(); + } +} + 1; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 3495b980..2790b0b4 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -39,7 +39,40 @@ sub new_from_mesh { ); # process facets - $mesh->slice_facet($print, $_) for 0..$#{$mesh->facets}; + { + my $apply_lines = sub { + my $lines = shift; + foreach my $layer_id (keys %$lines) { + my $layer = $print->layer($layer_id); + $layer->add_line($_) for @{ $lines->{$layer_id} }; + } + }; + Slic3r::parallelize( + disable => ($#{$mesh->facets} < 500), # don't parallelize when too few facets + items => [ 0..$#{$mesh->facets} ], + thread_cb => sub { + my $q = shift; + my $result_lines = {}; + while (defined (my $facet_id = $q->dequeue)) { + my $lines = $mesh->slice_facet($print, $facet_id); + foreach my $layer_id (keys %$lines) { + $result_lines->{$layer_id} ||= []; + push @{ $result_lines->{$layer_id} }, @{ $lines->{$layer_id} }; + } + } + return $result_lines; + }, + collect_cb => sub { + $apply_lines->($_[0]); + }, + no_threads_cb => sub { + for (0..$#{$mesh->facets}) { + my $lines = $mesh->slice_facet($print, $_); + $apply_lines->($lines); + } + }, + ); + } die "Invalid input file\n" if !@{$print->layers}; # remove last layer if empty diff --git a/lib/Slic3r/TriangleMesh.pm b/lib/Slic3r/TriangleMesh.pm index 6e0aca0b..32f02cf5 100644 --- a/lib/Slic3r/TriangleMesh.pm +++ b/lib/Slic3r/TriangleMesh.pm @@ -366,10 +366,13 @@ sub slice_facet { my $max_layer = int((unscale($max_z) - ($first_layer_height + $Slic3r::layer_height / 2)) / $Slic3r::layer_height) + 2; Slic3r::debugf "layers: min = %s, max = %s\n", $min_layer, $max_layer; + my $lines = {}; # layer_id => [ lines ] for (my $layer_id = $min_layer; $layer_id <= $max_layer; $layer_id++) { my $layer = $print->layer($layer_id); - $layer->add_line($_) for $self->intersect_facet($facet_id, $layer->slice_z); + $lines->{$layer_id} ||= []; + push @{ $lines->{$layer_id} }, $self->intersect_facet($facet_id, $layer->slice_z); } + return $lines; } sub intersect_facet {