Browse Source

Replace TriangleMesh with the XS port

Alessandro Ranellucci 11 years ago
parent
commit
566d38a472

+ 1 - 1
lib/Slic3r/Format/STL.pm

@@ -7,7 +7,7 @@ sub read_file {
     my $self = shift;
     my ($file) = @_;
     
-    my $tmesh = Slic3r::TriangleMesh::XS->new;
+    my $tmesh = Slic3r::TriangleMesh->new;
     $tmesh->ReadSTLFile(Slic3r::encode_path($file));
     $tmesh->repair;
     my ($vertices, $facets) = ($tmesh->vertices, $tmesh->facets);

+ 8 - 13
lib/Slic3r/GUI/Plater.pm

@@ -399,7 +399,6 @@ sub load_file {
                     : [0,0],
             ],
         );
-		$object->check_manifoldness;
         
         # we only consider the rotation of the first instance for now
         $object->rotate($model->objects->[$i]->instances->[0]->rotation)
@@ -1290,20 +1289,16 @@ sub changescale {
     $self->scale($scale);
 }
 
-sub check_manifoldness {
+sub needed_repair {
 	my $self = shift;
 	
-	if ($self->mesh_stats) {
-	    if ($self->get_model_object->needed_repair) {
-	        warn "Warning: the input file contains manifoldness errors. "
-	            . "Slic3r repaired it successfully by guessing what the correct shape should be, "
-	            . "but you might still want to inspect the G-code before printing.\n";
-	        $self->is_manifold(0);
-	    } else {
-	        $self->is_manifold(1);
-	    }
-	} else {
-    	$self->is_manifold($self->get_model_object->check_manifoldness);
+    if ($self->get_model_object->needed_repair) {
+        warn "Warning: the input file contains manifoldness errors. "
+            . "Slic3r repaired it successfully by guessing what the correct shape should be, "
+            . "but you might still want to inspect the G-code before printing.\n";
+        $self->is_manifold(0);
+    } else {
+        $self->is_manifold(1);
     }
 	return $self->is_manifold;
 }

+ 1 - 1
lib/Slic3r/GUI/SkeinPanel.pm

@@ -221,7 +221,7 @@ sub repair_stl {
         $dlg->Destroy;
     }
     
-    my $tmesh = Slic3r::TriangleMesh::XS->new();
+    my $tmesh = Slic3r::TriangleMesh->new;
     $tmesh->ReadSTLFile($input_file);
     $tmesh->repair;
     $tmesh->WriteOBJFile($output_file);

+ 13 - 17
lib/Slic3r/Model.pm

@@ -360,10 +360,9 @@ sub mesh {
     
     # this mesh won't be suitable for check_manifoldness as multiple
     # facets from different volumes may use the same vertices
-    return Slic3r::TriangleMesh->new(
-        vertices => $self->vertices,
-        facets   => [ map @{$_->facets}, @{$self->volumes} ],
-    );
+    my $mesh = Slic3r::TriangleMesh->new;
+    $mesh->ReadFromPerl($self->vertices, [ map @{$_->facets}, @{$self->volumes} ]);
+    return $mesh;
 }
 
 sub used_vertices {
@@ -381,6 +380,11 @@ sub center {
     return $self->bounding_box->center;
 }
 
+sub center_2D {
+    my $self = shift;
+    return $self->bounding_box->center_2D;
+}
+
 sub bounding_box {
     my $self = shift;
     
@@ -458,17 +462,9 @@ sub facets_count {
     return sum(map $_->facets_count, @{$self->volumes});
 }
 
-sub check_manifoldness {
-    my $self = shift;
-    return (first { !$_->mesh->check_manifoldness } @{$self->volumes}) ? 0 : 1;
-}
-
 sub needed_repair {
     my $self = shift;
-    
-    return $self->mesh_stats
-        && first { $self->mesh_stats->{$_} > 0 }
-            qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges);
+    return (first { !$_->mesh->needed_repair } @{$self->volumes}) ? 0 : 1;
 }
 
 sub print_info {
@@ -507,10 +503,10 @@ has 'facets'        => (is => 'rw', default => sub { [] });
 
 sub mesh {
     my $self = shift;
-    return Slic3r::TriangleMesh->new(
-        vertices => $self->object->vertices,
-        facets   => $self->facets,
-    );
+    
+    my $mesh = Slic3r::TriangleMesh->new;
+    $mesh->ReadFromPerl($self->object->vertices, $self->facets);
+    return $mesh;
 }
 
 sub facets_count {

+ 3 - 4
lib/Slic3r/Print.pm

@@ -128,26 +128,25 @@ sub add_model {
         $self->regions->[$_] //= Slic3r::Print::Region->new for 0..$#meshes;
         
         foreach my $mesh (grep $_, @meshes) {
-            $mesh->check_manifoldness;
-            
             # the order of these transformations must be the same as the one used in plater
             # to make the object positioning consistent with the visual preview
             
             # we ignore the per-instance transformations currently and only 
             # consider the first one
             if ($object->instances && @{$object->instances}) {
-                $mesh->rotate($object->instances->[0]->rotation, $object->center);
+                $mesh->rotate($object->instances->[0]->rotation, $object->center_2D);
                 $mesh->scale($object->instances->[0]->scaling_factor);
             }
             
             $mesh->scale(1 / &Slic3r::SCALING_FACTOR);
+            $mesh->repair;
         }
         
         # we also align object after transformations so that we only work with positive coordinates
         # and the assumption that bounding_box === size works
         my $bb = Slic3r::Geometry::BoundingBox->new_from_points_3D([ map @{$_->used_vertices}, grep $_, @meshes ]);
         my @align2 = map -$bb->extents->[$_][MIN], (X,Y,Z);
-        $_->move(@align2) for grep $_, @meshes;
+        $_->translate(@align2) for grep $_, @meshes;
         
         # initialize print object
         push @{$self->objects}, Slic3r::Print::Object->new(

+ 1 - 1
lib/Slic3r/Print/Object.pm

@@ -146,7 +146,7 @@ sub slice {
         my $mesh = $self->meshes->[$region_id] // next;  # ignore undef meshes
         
         {
-            my $m = Slic3r::TriangleMesh::XS->new;
+            my $m = Slic3r::TriangleMesh->new;
             $m->ReadFromPerl($mesh->vertices, $mesh->facets);
             $m->repair;
             my $lines = $m->slice([ map $_->slice_z, @{$self->layers} ]);

+ 2 - 4
lib/Slic3r/Test.pm

@@ -66,10 +66,8 @@ sub model {
         return undef;
     }
     
-    my $mesh = Slic3r::TriangleMesh->new(
-        vertices    => $vertices,
-        facets      => $facets,
-    );
+    my $mesh = Slic3r::TriangleMesh->new;
+    $mesh->ReadFromperl($vertices, $facets);
     $mesh->scale_xyz($params{scale_xyz}) if $params{scale_xyz};
     $mesh->scale($params{scale}) if $params{scale};
     

+ 13 - 192
lib/Slic3r/TriangleMesh.pm

@@ -1,173 +1,17 @@
 package Slic3r::TriangleMesh;
-use Moo;
+use strict;
+use warnings;
 
-use List::Util qw(reduce min max first);
-use Slic3r::Geometry qw(X Y Z A B unscale same_point);
+use List::Util qw(first);
+use Slic3r::Geometry qw(X Y);
 use Slic3r::Geometry::Clipper qw(union_ex offset);
-use Storable;
 
-# public
-has 'vertices'      => (is => 'ro', required => 1);         # id => [$x,$y,$z]
-has 'facets'        => (is => 'ro', required => 1);         # id => [ $v1_id, $v2_id, $v3_id ]
-
-# private
-has 'edges'         => (is => 'rw'); # id => [ $v1_id, $v2_id ]
-has 'facets_edges'  => (is => 'rw'); # id => [ $e1_id, $e2_id, $e3_id ]
-has 'edges_facets'  => (is => 'rw'); # id => [ $f1_id, $f2_id, (...) ]
-
-use constant MIN => 0;
-use constant MAX => 1;
-
-sub analyze {
-    my $self = shift;
-    
-    return if defined $self->edges;
-    $self->edges([]);
-    $self->facets_edges([]);
-    $self->edges_facets([]);
-    my %table = ();  # edge_coordinates => edge_id
-    my $vertices = $self->vertices;  # save method calls
-    
-    for (my $facet_id = 0; $facet_id <= $#{$self->facets}; $facet_id++) {
-        my $facet = $self->facets->[$facet_id];
-        $self->facets_edges->[$facet_id] = [];
-        
-        # reorder vertices so that the first one is the one with lowest Z
-        # this is needed to get all intersection lines in a consistent order
-        # (external on the right of the line)
-        {
-            my $lowest_vertex_idx = reduce {
-                $vertices->[ $facet->[$a] ][Z] < $vertices->[ $facet->[$b] ][Z] ? $a : $b
-            } -3 .. -1;
-            @$facet[-3..-1] = (@$facet[$lowest_vertex_idx..-1], @$facet[-3..($lowest_vertex_idx-1)]);
-        }
-        
-        # ignore the normal if provided
-        my @vertices = @$facet[-3..-1];
-        
-        foreach my $edge ($self->_facet_edges($facet_id)) {
-            my $edge_coordinates = join ';', sort @$edge;
-            my $edge_id = $table{$edge_coordinates};
-            if (!defined $edge_id) {
-                # Note that the order of vertices in $self->edges is *casual* because it is only
-                # good for one of the two adjacent facets. For this reason, it must not be used
-                # when dealing with single facets.
-                push @{$self->edges}, $edge;
-                $edge_id = $#{$self->edges};
-                $table{$edge_coordinates} = $edge_id;
-                $self->edges_facets->[$edge_id] = [];
-            }
-            
-            push @{$self->facets_edges->[$facet_id]}, $edge_id;
-            push @{$self->edges_facets->[$edge_id]}, $facet_id;
-        }
-    }
-}
-
-sub merge {
-    my $class = shift;
-    my @meshes = @_;
-    
-    my $vertices = [];
-    my $facets = [];
-    
-    foreach my $mesh (@meshes) {
-        my $v_offset = @$vertices;
-        push @$vertices, @{$mesh->vertices};
-        push @$facets, map {
-            my $f = [@$_];
-            $f->[$_] += $v_offset for -3..-1;
-            $f;
-        } @{$mesh->facets};
-    }
-    
-    return $class->new(vertices => $vertices, facets => $facets);
-}
-
-sub clone {
-  Storable::dclone($_[0])
-}
-
-sub check_manifoldness {
+sub needed_repair {
     my $self = shift;
     
-    $self->analyze;
-    
-    # look for any edges belonging to an odd number of facets
-    # we should actually check that each pair of facets belonging to this edge
-    # has compatible winding order
-    my ($first_bad_edge_id) =
-        grep { @{ $self->edges_facets->[$_] } % 2 } 0..$#{$self->edges_facets};
-    if (defined $first_bad_edge_id) {
-        warn sprintf "Warning: The input file contains a hole near edge %f,%f,%f-%f,%f,%f (not manifold). "
-            . "You might want to repair it and retry, or to check the resulting G-code before printing anyway.\n",
-            map @{$self->vertices->[$_]}, @{$self->edges->[$first_bad_edge_id]};
-        return 0;
-    }
-    
-    # empty the edges array as we don't really need it anymore
-    @{$self->edges} = ();
-    
-    return 1;
-}
-
-sub rotate {
-    my $self = shift;
-    my ($deg, $center) = @_;
-    return if $deg == 0;
-    
-    my $rad = Slic3r::Geometry::deg2rad($deg);
-    
-    # transform vertex coordinates
-    foreach my $vertex (@{$self->vertices}) {
-        @$vertex = (@{ +(Slic3r::Geometry::rotate_points($rad, $center, [ $vertex->[X], $vertex->[Y] ]))[0] }, $vertex->[Z]);
-    }
-}
-
-sub scale {
-    my $self = shift;
-    my ($factor) = @_;
-    return if $factor == 1;
-    
-    # transform vertex coordinates
-    foreach my $vertex (@{$self->vertices}) {
-        $vertex->[$_] *= $factor for X,Y,Z;
-    }
-}
-
-sub scale_xyz {
-    my $self = shift;
-    my ($versor) = @_;
-    
-    # transform vertex coordinates
-    foreach my $vertex (@{$self->vertices}) {
-        $vertex->[$_] *= $versor->[$_] for X,Y,Z;
-    }
-}
-
-sub move {
-    my $self = shift;
-    my (@shift) = @_;
-    
-    # transform vertex coordinates
-    foreach my $vertex (@{$self->vertices}) {
-        $vertex->[$_] += $shift[$_] || 0 for X,Y,Z;
-    }
-}
-
-sub align_to_origin {
-    my $self = shift;
-    
-    # calculate the displacements needed to 
-    # have lowest value for each axis at coordinate 0
-    my $bb = $self->bounding_box;
-    $self->move(map -$bb->extents->[$_][MIN], X,Y,Z);
-}
-
-sub center_around_origin {
-    my $self = shift;
-    
-    $self->move(map -$_, @{ $self->center });
+    my $stats = $self->stats;
+    return (first { $stats->{$_} > 0 }
+        qw(degenerate_facets edges_fixed facets_removed facets_added facets_reversed backwards_edges)) ? 1 : 0;
 }
 
 sub center {
@@ -175,29 +19,9 @@ sub center {
     return $self->bounding_box->center;
 }
 
-sub duplicate {
-    my $self = shift;
-    my (@shifts) = @_;
-    
-    my @new_facets = ();
-    foreach my $facet (@{$self->facets}) {
-        # transform vertex coordinates
-        my ($normal, @vertices) = @$facet;
-        foreach my $shift (@shifts) {
-            push @new_facets, [ $normal ];
-            foreach my $vertex (@vertices) {
-                push @{$self->vertices}, [ map $self->vertices->[$vertex][$_] + ($shift->[$_] || 0), (X,Y,Z) ];
-                push @{$new_facets[-1]}, $#{$self->vertices};
-            }
-        }
-    }
-    push @{$self->facets}, @new_facets;
-    $self->BUILD;
-}
-
 sub used_vertices {
     my $self = shift;
-    return [ map $self->vertices->[$_], map @$_, @{$self->facets} ];
+    return $self->vertices;
 }
 
 sub bounding_box {
@@ -205,20 +29,17 @@ sub bounding_box {
     return Slic3r::Geometry::BoundingBox->new_from_points_3D($self->used_vertices);
 }
 
-sub size {
-    my $self = shift;
-    return $self->bounding_box->size;
-}
-
 # this will return *scaled* expolygons, so it is expected to be run
 # on unscaled meshes
 sub horizontal_projection {
     my $self = shift;
     
+    my ($facets, $vertices) = ($self->facets, $self->vertices);
+    
     my @f = ();
-    foreach my $facet (@{$self->facets}) {
+    foreach my $facet (@$facets) {
         push @f, Slic3r::Polygon->new(
-            map [ map $_ / &Slic3r::SCALING_FACTOR, @{$self->vertices->[$_]}[X,Y] ], @$facet
+            map [ map $_ / &Slic3r::SCALING_FACTOR, @{$vertices->[$_]}[X,Y] ], @$facet
         );
     }
     

+ 1 - 1
slic3r.pl

@@ -101,7 +101,7 @@ if (@ARGV) {  # slicing from command line
             
             my $output_file = $file;
             $output_file =~ s/\.(stl)$/_fixed.obj/i;
-            my $tmesh = Slic3r::TriangleMesh::XS->new();
+            my $tmesh = Slic3r::TriangleMesh->new;
             $tmesh->ReadSTLFile($file);
             $tmesh->repair;
             $tmesh->WriteOBJFile($output_file);

+ 2 - 1
t/loops.t

@@ -39,7 +39,8 @@ use Slic3r::Test;
         [ [5,15,0],   [15,15,10], [5,15,10]   ],
         [ [5,5,0],    [5,15,10],  [5,5,10]    ];
     
-    my $mesh = Slic3r::TriangleMesh->new(vertices => \@vertices, facets => \@facets);
+    my $mesh = Slic3r::TriangleMesh->new;
+    $mesh->ReadFromPerl(\@vertices, \@facets);
     $mesh->analyze;
     my @lines = map $mesh->intersect_facet($_, 10), 0..$#facets;
     my $loops = Slic3r::TriangleMesh::make_loops(\@lines);

Some files were not shown because too many files changed in this diff