diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm
index 44b2a9bf5..1cd67fb73 100644
--- a/lib/Slic3r.pm
+++ b/lib/Slic3r.pm
@@ -56,6 +56,7 @@ use Slic3r::ExPolygon;
 use Slic3r::ExtrusionLoop;
 use Slic3r::ExtrusionPath;
 use Slic3r::Fill;
+use Slic3r::Fill2;
 use Slic3r::Flow;
 use Slic3r::Format::AMF;
 use Slic3r::Format::OBJ;
diff --git a/lib/Slic3r/Fill/Base.pm b/lib/Slic3r/Fill/Base.pm
index 75c8e03e6..482594a31 100644
--- a/lib/Slic3r/Fill/Base.pm
+++ b/lib/Slic3r/Fill/Base.pm
@@ -8,6 +8,16 @@ has 'spacing'             => (is => 'rw'); # in unscaled coordinates
 has 'loop_clipping'       => (is => 'rw', default => sub { 0 }); # in scaled coordinates
 has 'bounding_box'        => (is => 'ro', required => 0);  # Slic3r::Geometry::BoundingBox object
 
+sub set_spacing {
+    my ($self, $spacing) = @_;
+    $self->spacing($spacing);
+}
+
+sub set_angle {
+    my ($self, $angle) = @_;
+    $self->angle($angle);
+}
+
 sub adjust_solid_spacing {
     my $self = shift;
     my %params = @_;
diff --git a/lib/Slic3r/Fill2.pm b/lib/Slic3r/Fill2.pm
new file mode 100644
index 000000000..9e2714b3b
--- /dev/null
+++ b/lib/Slic3r/Fill2.pm
@@ -0,0 +1,294 @@
+# This is derived from Fill.pm
+# and it uses the C++ fillers.
+package Slic3r::Fill2;
+use Moo;
+
+use List::Util qw(max);
+use Slic3r::ExtrusionPath ':roles';
+
+use Slic3r::Flow ':roles';
+use Slic3r::Geometry qw(X Y PI scale chained_path deg2rad);
+use Slic3r::Geometry::Clipper qw(union union_ex diff diff_ex intersection_ex offset offset2);
+use Slic3r::Surface ':types';
+
+has 'bounding_box' => (is => 'ro', required => 0);
+has 'fillers'   => (is => 'rw', default => sub { {} });
+
+sub filler {
+    my $self = shift;
+    my ($filler) = @_;
+    
+    if (!ref $self) {
+       return Slic3r::Filler->new_from_type($filler);
+    }
+
+    print "Filler: ", $filler, "\n";
+    $self->fillers->{$filler} ||= Slic3r::Filler->new_from_type($filler);
+    $self->fillers->{$filler}->set_bounding_box($self->bounding_box);
+    return $self->fillers->{$filler};
+}
+
+
+# Generate infills for Slic3r::Layer::Region.
+# The Slic3r::Layer::Region at this point of time may contain
+# surfaces of various types (internal/bridge/top/bottom/solid).
+# The infills are generated on the groups of surfaces with a compatible type. 
+# Returns an array of Slic3r::ExtrusionPath::Collection objects containing the infills generaed now
+# and the thin fills generated by generate_perimeters().
+sub make_fill {
+    my $self = shift;
+    # of type - C++: LayerRegion, Perl: Slic3r::Layer::Region
+    my ($layerm) = @_;
+    
+    Slic3r::debugf "Filling layer %d:\n", $layerm->layer->id;
+    
+    my $fill_density            = $layerm->region->config->fill_density;
+    my $infill_flow             = $layerm->flow(FLOW_ROLE_INFILL);
+    my $solid_infill_flow       = $layerm->flow(FLOW_ROLE_SOLID_INFILL);
+    my $top_solid_infill_flow   = $layerm->flow(FLOW_ROLE_TOP_SOLID_INFILL);
+    
+    # Surfaces are of the type Slic3r::Surface
+    my @surfaces = ();
+    
+    # merge adjacent surfaces
+    # in case of bridge surfaces, the ones with defined angle will be attached to the ones
+    # without any angle (shouldn't this logic be moved to process_external_surfaces()?)
+    {
+        my @surfaces_with_bridge_angle = grep { $_->bridge_angle >= 0 } @{$layerm->fill_surfaces};
+        
+        # group surfaces by distinct properties
+        # group is of type Slic3r::SurfaceCollection
+        my @groups = @{$layerm->fill_surfaces->group};
+        
+        # merge compatible groups (we can generate continuous infill for them)
+        {
+            # cache flow widths and patterns used for all solid groups
+            # (we'll use them for comparing compatible groups)
+            my @is_solid = my @fw = my @pattern = ();
+            for (my $i = 0; $i <= $#groups; $i++) {
+                # we can only merge solid non-bridge surfaces, so discard
+                # non-solid surfaces
+                if ($groups[$i][0]->is_solid && (!$groups[$i][0]->is_bridge || $layerm->layer->id == 0)) {
+                    $is_solid[$i] = 1;
+                    $fw[$i] = ($groups[$i][0]->surface_type == S_TYPE_TOP)
+                        ? $top_solid_infill_flow->width
+                        : $solid_infill_flow->width;
+                    $pattern[$i] = $groups[$i][0]->is_external
+                        ? $layerm->region->config->external_fill_pattern
+                        : 'rectilinear';
+                } else {
+                    $is_solid[$i]   = 0;
+                    $fw[$i]         = 0;
+                    $pattern[$i]    = 'none';
+                }
+            }
+            
+            # loop through solid groups
+            for (my $i = 0; $i <= $#groups; $i++) {
+                next if !$is_solid[$i];
+                
+                # find compatible groups and append them to this one
+                for (my $j = $i+1; $j <= $#groups; $j++) {
+                    next if !$is_solid[$j];
+                
+                    if ($fw[$i] == $fw[$j] && $pattern[$i] eq $pattern[$j]) {
+                        # groups are compatible, merge them
+                        push @{$groups[$i]}, @{$groups[$j]};
+                        splice @groups,     $j, 1;
+                        splice @is_solid,   $j, 1;
+                        splice @fw,         $j, 1;
+                        splice @pattern,    $j, 1;
+                    }
+                }
+            }
+        }
+        
+        # give priority to bridges
+        @groups = sort { ($a->[0]->bridge_angle >= 0) ? -1 : 0 } @groups;
+        
+        foreach my $group (@groups) {
+            # Make a union of polygons defining the infiill regions of a group, use a safety offset.
+            my $union_p = union([ map $_->p, @$group ], 1);
+            
+            # Subtract surfaces having a defined bridge_angle from any other, use a safety offset.
+            if (@surfaces_with_bridge_angle && $group->[0]->bridge_angle < 0) {
+                $union_p = diff(
+                    $union_p,
+                    [ map $_->p, @surfaces_with_bridge_angle ],
+                    1,
+                );
+            }
+            
+            # subtract any other surface already processed
+            #FIXME Vojtech: Because the bridge surfaces came first, they are subtracted twice!
+            my $union = diff_ex(
+                $union_p,
+                [ map $_->p, @surfaces ],
+                1,
+            );
+            
+            push @surfaces, map $group->[0]->clone(expolygon => $_), @$union;
+        }
+    }
+    
+    # we need to detect any narrow surfaces that might collapse
+    # when adding spacing below
+    # such narrow surfaces are often generated in sloping walls
+    # by bridge_over_infill() and combine_infill() as a result of the
+    # subtraction of the combinable area from the layer infill area,
+    # which leaves small areas near the perimeters
+    # we are going to grow such regions by overlapping them with the void (if any)
+    # TODO: detect and investigate whether there could be narrow regions without
+    # any void neighbors
+    {
+        my $distance_between_surfaces = max(
+            $infill_flow->scaled_spacing,
+            $solid_infill_flow->scaled_spacing,
+            $top_solid_infill_flow->scaled_spacing,
+        );
+        my $collapsed = diff(
+            [ map @{$_->expolygon}, @surfaces ],
+            offset2([ map @{$_->expolygon}, @surfaces ], -$distance_between_surfaces/2, +$distance_between_surfaces/2),
+            1,
+        );
+        push @surfaces, map Slic3r::Surface->new(
+            expolygon       => $_,
+            surface_type    => S_TYPE_INTERNALSOLID,
+        ), @{intersection_ex(
+            offset($collapsed, $distance_between_surfaces),
+            [
+                (map @{$_->expolygon}, grep $_->surface_type == S_TYPE_INTERNALVOID, @surfaces),
+                (@$collapsed),
+            ],
+            1,
+        )};
+    }
+    
+    if (0) {
+        require "Slic3r/SVG.pm";
+        Slic3r::SVG::output("fill_" . $layerm->print_z . ".svg",
+            expolygons      => [ map $_->expolygon, grep !$_->is_solid, @surfaces ],
+            red_expolygons  => [ map $_->expolygon, grep  $_->is_solid, @surfaces ],
+        );
+    }
+    
+    # Fills are of perl type Slic3r::ExtrusionPath::Collection, c++ type ExtrusionEntityCollection
+    my @fills = ();
+    SURFACE: foreach my $surface (@surfaces) {
+        next if $surface->surface_type == S_TYPE_INTERNALVOID;
+        my $filler          = $layerm->region->config->fill_pattern;
+        my $density         = $fill_density;
+        my $role = ($surface->surface_type == S_TYPE_TOP) ? FLOW_ROLE_TOP_SOLID_INFILL
+            : $surface->is_solid ? FLOW_ROLE_SOLID_INFILL
+            : FLOW_ROLE_INFILL;
+        my $is_bridge       = $layerm->layer->id > 0 && $surface->is_bridge;
+        my $is_solid        = $surface->is_solid;
+        
+        if ($surface->is_solid) {
+            $density = 100;
+            $filler = 'rectilinear';
+            if ($surface->is_external && !$is_bridge) {
+                $filler = $layerm->region->config->external_fill_pattern;
+            }
+        } else {
+            next SURFACE unless $density > 0;
+        }
+        
+        # get filler object
+        my $f = $self->filler($filler);
+        
+        # calculate the actual flow we'll be using for this infill
+        my $h = $surface->thickness == -1 ? $layerm->layer->height : $surface->thickness;
+        my $flow = $layerm->region->flow(
+            $role,
+            $h,
+            $is_bridge || $f->use_bridge_flow,
+            $layerm->layer->id == 0,
+            -1,
+            $layerm->layer->object,
+        );
+        
+        # calculate flow spacing for infill pattern generation
+        my $using_internal_flow = 0;
+        if (!$is_solid && !$is_bridge) {
+            # it's internal infill, so we can calculate a generic flow spacing 
+            # for all layers, for avoiding the ugly effect of
+            # misaligned infill on first layer because of different extrusion width and
+            # layer height
+            my $internal_flow = $layerm->region->flow(
+                FLOW_ROLE_INFILL,
+                $layerm->layer->object->config->layer_height,  # TODO: handle infill_every_layers?
+                0,  # no bridge
+                0,  # no first layer
+                -1, # auto width
+                $layerm->layer->object,
+            );
+            $f->set_spacing($internal_flow->spacing);
+            $using_internal_flow = 1;
+        } else {
+            $f->set_spacing($flow->spacing);
+        }
+        
+        $f->set_layer_id($layerm->layer->id);
+        $f->set_z($layerm->layer->print_z);
+        $f->set_angle(deg2rad($layerm->region->config->fill_angle));
+        $f->set_loop_clipping(scale($flow->nozzle_diameter) * &Slic3r::LOOP_CLIPPING_LENGTH_OVER_NOZZLE_DIAMETER);
+        
+        # apply half spacing using this flow's own spacing and generate infill
+        my @polylines = $f->fill_surface(
+            $surface,
+            density         => $density/100,
+            layer_height    => $h,
+        );
+        next unless @polylines;
+
+        
+        # calculate actual flow from spacing (which might have been adjusted by the infill
+        # pattern generator)
+        if ($using_internal_flow) {
+            # if we used the internal flow we're not doing a solid infill
+            # so we can safely ignore the slight variation that might have
+            # been applied to $f->flow_spacing
+        } else {
+            $flow = Slic3r::Flow->new_from_spacing(
+                spacing         => $f->spacing,
+                nozzle_diameter => $flow->nozzle_diameter,
+                layer_height    => $h,
+                bridge          => $is_bridge || $f->use_bridge_flow,
+            );
+        }
+
+        # save into layer
+        {
+            my $role = $is_bridge ? EXTR_ROLE_BRIDGE
+                : $is_solid ? (($surface->surface_type == S_TYPE_TOP) ? EXTR_ROLE_TOPSOLIDFILL : EXTR_ROLE_SOLIDFILL)
+                : EXTR_ROLE_FILL;
+            
+            push @fills, my $collection = Slic3r::ExtrusionPath::Collection->new;
+            # Only concentric fills are not sorted.
+            $collection->no_sort($f->no_sort);
+            $collection->append(
+                map Slic3r::ExtrusionPath->new(
+                    polyline    => $_,
+                    role        => $role,
+                    mm3_per_mm  => $flow->mm3_per_mm,
+                    width       => $flow->width,
+                    height      => $flow->height,
+                ), map @$_, @polylines,
+            );
+        }
+    }
+    
+    # add thin fill regions
+    # thin_fills are of C++ Slic3r::ExtrusionEntityCollection, perl type Slic3r::ExtrusionPath::Collection
+    # Unpacks the collection, creates multiple collections per path.
+    # The path type could be ExtrusionPath, ExtrusionLoop or ExtrusionEntityCollection.
+    # Why the paths are unpacked?
+    foreach my $thin_fill (@{$layerm->thin_fills}) {
+        push @fills, Slic3r::ExtrusionPath::Collection->new($thin_fill);
+    }
+    
+    return @fills;
+}
+
+1;
diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm
index 897268fe0..42a85e2b4 100644
--- a/lib/Slic3r/Print/Object.pm
+++ b/lib/Slic3r/Print/Object.pm
@@ -20,6 +20,13 @@ sub fill_maker {
     return Slic3r::Fill->new(bounding_box => $self->bounding_box);
 }
 
+# Vojtech's implementation: Create the C++ filler.
+# TODO: lazy
+sub fill_maker2 {
+    my $self = shift;
+    return Slic3r::Fill2->new(bounding_box => $self->bounding_box);
+}
+
 sub region_volumes {
     my $self = shift;
     return [ map $self->get_region_volumes($_), 0..($self->region_count - 1) ];
diff --git a/xs/src/libslic3r/Fill/FillRectilinear2.cpp b/xs/src/libslic3r/Fill/FillRectilinear2.cpp
index b521cc696..1f6e64784 100644
--- a/xs/src/libslic3r/Fill/FillRectilinear2.cpp
+++ b/xs/src/libslic3r/Fill/FillRectilinear2.cpp
@@ -14,7 +14,7 @@
 
 #include "FillRectilinear2.hpp"
 
-#define SLIC3R_DEBUG
+// #define SLIC3R_DEBUG
 
 #ifdef SLIC3R_DEBUG
 #include "SVG.hpp"