mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-10-31 04:31:15 -06:00 
			
		
		
		
	Refactoring: new Slic3r::Model class to represent files
This commit is contained in:
		
							parent
							
								
									c0322ec703
								
							
						
					
					
						commit
						f90520ed06
					
				
					 14 changed files with 255 additions and 88 deletions
				
			
		
							
								
								
									
										1
									
								
								MANIFEST
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								MANIFEST
									
										
									
									
									
								
							|  | @ -15,6 +15,7 @@ lib/Slic3r/Fill/Flowsnake.pm | |||
| lib/Slic3r/Fill/HilbertCurve.pm | ||||
| lib/Slic3r/Fill/Honeycomb.pm | ||||
| lib/Slic3r/Fill/Line.pm | ||||
| lib/Slic3r/Fill/Model.pm | ||||
| lib/Slic3r/Fill/OctagramSpiral.pm | ||||
| lib/Slic3r/Fill/PlanePath.pm | ||||
| lib/Slic3r/Fill/Rectilinear.pm | ||||
|  |  | |||
|  | @ -41,6 +41,7 @@ use Slic3r::GCode; | |||
| use Slic3r::Geometry qw(PI); | ||||
| use Slic3r::Layer; | ||||
| use Slic3r::Line; | ||||
| use Slic3r::Model; | ||||
| use Slic3r::Point; | ||||
| use Slic3r::Polygon; | ||||
| use Slic3r::Polyline; | ||||
|  |  | |||
|  | @ -25,15 +25,21 @@ sub read_file { | |||
|      | ||||
|     close $fh; | ||||
|      | ||||
|     $_ = Slic3r::TriangleMesh->new(vertices => $vertices, facets => $_) | ||||
|         for values %$meshes_by_material; | ||||
|      | ||||
|     return $materials, $meshes_by_material; | ||||
|     my $model = Slic3r::Model->new; | ||||
|     my $object = $model->add_object(vertices => $vertices); | ||||
|     foreach my $material (keys %$meshes_by_material) { | ||||
|         push @{$model->materials}, $material;  # TODO: we should not add duplicate materials | ||||
|         $object->add_volume( | ||||
|             material_id => $#{$model->materials}, | ||||
|             facets      => $meshes_by_material->{$material}, | ||||
|         ); | ||||
|     } | ||||
|     return $model; | ||||
| } | ||||
| 
 | ||||
| sub write_file { | ||||
|     my $self = shift; | ||||
|     my ($file, $materials, $meshes_by_material) = @_; | ||||
|     my ($file, $model, %params) = @_; | ||||
|      | ||||
|     my %vertices_offset = (); | ||||
|      | ||||
|  | @ -42,20 +48,20 @@ sub write_file { | |||
|     printf $fh qq{<?xml version="1.0" encoding="UTF-8"?>\n}; | ||||
|     printf $fh qq{<amf unit="millimeter">\n}; | ||||
|     printf $fh qq{  <metadata type="cad">Slic3r %s</metadata>\n}, $Slic3r::VERSION; | ||||
|     foreach my $material_id (keys %$materials) { | ||||
|         printf $fh qq{  <material id="%s">\n}, $material_id; | ||||
|         for (keys %{$materials->{$material_id}}) { | ||||
|              printf $fh qq{    <metadata type=\"%s\">%s</metadata>\n}, $_, $materials->{$material_id}{$_}; | ||||
|     for my $material_id (0 .. $#{ $model->materials }) { | ||||
|         my $material = $model->materials->[$material_id]; | ||||
|         printf $fh qq{  <material id="%d">\n}, $material_id; | ||||
|         for (keys %$material) { | ||||
|              printf $fh qq{    <metadata type=\"%s\">%s</metadata>\n}, $_, $material->{$_}; | ||||
|         } | ||||
|         printf $fh qq{  </material>\n}; | ||||
|     } | ||||
|     printf $fh qq{  <object id="0">\n}; | ||||
|     for my $object_id (0 .. $#{ $model->objects }) { | ||||
|         my $object = $model->objects->[$object_id]; | ||||
|         printf $fh qq{  <object id="%d">\n}, $object_id; | ||||
|         printf $fh qq{    <mesh>\n}; | ||||
|         printf $fh qq{      <vertices>\n}; | ||||
|     my $vertices_count = 0; | ||||
|     foreach my $mesh (values %$meshes_by_material) { | ||||
|         $vertices_offset{$mesh} = $vertices_count; | ||||
|         foreach my $vertex (@{$mesh->vertices}, ) { | ||||
|         foreach my $vertex (@{$object->vertices}, ) { | ||||
|             printf $fh qq{        <vertex>\n}; | ||||
|             printf $fh qq{          <coordinates>\n}; | ||||
|             printf $fh qq{            <x>%s</x>\n}, $vertex->[X]; | ||||
|  | @ -63,24 +69,21 @@ sub write_file { | |||
|             printf $fh qq{            <z>%s</z>\n}, $vertex->[Z]; | ||||
|             printf $fh qq{          </coordinates>\n}; | ||||
|             printf $fh qq{        </vertex>\n}; | ||||
|             $vertices_count++; | ||||
|         } | ||||
|         } | ||||
|         printf $fh qq{      </vertices>\n}; | ||||
|     foreach my $material_id (sort keys %$meshes_by_material) { | ||||
|         my $mesh = $meshes_by_material->{$material_id}; | ||||
|         foreach my $volume (@{ $object->volumes }) { | ||||
|             printf $fh qq{      <volume%s>\n}, | ||||
|             ($material_id eq '_') ? '' : " materialid=\"$material_id\""; | ||||
|         foreach my $facet (@{$mesh->facets}) { | ||||
|                 (!defined $volume->material_id) ? '' : (sprintf ' materialid="%s"', $volume->material_id); | ||||
|             foreach my $facet (@{$volume->facets}) { | ||||
|                 printf $fh qq{        <triangle>\n}; | ||||
|             printf $fh qq{          <v%d>%d</v%d>\n}, $_, $facet->[$_] + $vertices_offset{$mesh}, $_ | ||||
|                 for -3..-1; | ||||
|                 printf $fh qq{          <v%d>%d</v%d>\n}, $_, $facet->[$_], $_ for -3..-1; | ||||
|                 printf $fh qq{        </triangle>\n}; | ||||
|             } | ||||
|             printf $fh qq{      </volume>\n}; | ||||
|         } | ||||
|         printf $fh qq{    </mesh>\n}; | ||||
|         printf $fh qq{  </object>\n}; | ||||
|     } | ||||
|     printf $fh qq{</amf>\n}; | ||||
|     close $fh; | ||||
| } | ||||
|  |  | |||
|  | @ -71,7 +71,7 @@ sub end_element { | |||
|     } elsif ($data->{LocalName} eq 'triangle') { | ||||
|         push @{$self->{_volume}}, $self->{_triangle}; | ||||
|         $self->{_triangle} = undef; | ||||
|     } elsif ($self->{_vertex_idx} && $data->{LocalName} =~ /^v[123]$/) { | ||||
|     } elsif (defined $self->{_vertex_idx} && $data->{LocalName} =~ /^v[123]$/) { | ||||
|         $self->{_vertex_idx} = undef; | ||||
|     } elsif ($data->{LocalName} eq 'material') { | ||||
|         $self->{_materials}{ $self->{_material_id} } = $self->{_material}; | ||||
|  |  | |||
|  | @ -17,7 +17,10 @@ sub read_file { | |||
|     } | ||||
|     close $fh; | ||||
|      | ||||
|     return Slic3r::TriangleMesh->new(vertices => $vertices, facets => $facets); | ||||
|     my $model = Slic3r::Model->new; | ||||
|     my $object = $model->add_object(vertices => $vertices); | ||||
|     my $volume = $object->add_volume(facets => $facets); | ||||
|     return $model; | ||||
| } | ||||
| 
 | ||||
| 1; | ||||
|  |  | |||
|  | @ -117,7 +117,10 @@ sub read_file { | |||
|         } | ||||
|     } | ||||
|      | ||||
|     return Slic3r::TriangleMesh->new(vertices => $vertices, facets => $facets); | ||||
|     my $model = Slic3r::Model->new; | ||||
|     my $object = $model->add_object(vertices => $vertices); | ||||
|     my $volume = $object->add_volume(facets => $facets); | ||||
|     return $model; | ||||
| } | ||||
| 
 | ||||
| sub _read_ascii { | ||||
|  | @ -161,13 +164,13 @@ sub _read_binary { | |||
| 
 | ||||
| sub write_file { | ||||
|     my $self = shift; | ||||
|     my ($file, $mesh, $binary) = @_; | ||||
|     my ($file, $model, %params) = @_; | ||||
|      | ||||
|     open my $fh, '>', $file; | ||||
|      | ||||
|     $binary | ||||
|         ? _write_binary($fh, $mesh) | ||||
|         : _write_ascii($fh, $mesh); | ||||
|     $params{binary} | ||||
|         ? _write_binary($fh, $model->mesh) | ||||
|         : _write_ascii($fh, $model->mesh); | ||||
|      | ||||
|     close $fh; | ||||
| } | ||||
|  |  | |||
|  | @ -296,7 +296,7 @@ sub load_file { | |||
|     my $process_dialog = Wx::ProgressDialog->new('Loading…', "Processing input file…", 100, $self, 0); | ||||
|     $process_dialog->Pulse; | ||||
|     local $SIG{__WARN__} = Slic3r::GUI::warning_catcher($self); | ||||
|     $self->{print}->add_object_from_file($input_file); | ||||
|     $self->{print}->add_objects_from_file($input_file); | ||||
|     my $obj_idx = $#{$self->{print}->objects}; | ||||
|     $process_dialog->Destroy; | ||||
|      | ||||
|  | @ -631,12 +631,10 @@ sub on_export_failed { | |||
| sub export_stl { | ||||
|     my $self = shift; | ||||
|          | ||||
|     my $print = $self->{print}; | ||||
|          | ||||
|     # select output file | ||||
|     my $output_file = $main::opt{output}; | ||||
|     { | ||||
|         $output_file = $print->expanded_output_filepath($output_file); | ||||
|         $output_file = $self->{print}->expanded_output_filepath($output_file); | ||||
|         $output_file =~ s/\.gcode$/.stl/i; | ||||
|         my $dlg = Wx::FileDialog->new($self, 'Save STL file as:', dirname($output_file), | ||||
|             basename($output_file), $Slic3r::GUI::SkeinPanel::model_wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT); | ||||
|  | @ -648,23 +646,28 @@ sub export_stl { | |||
|         $dlg->Destroy; | ||||
|     } | ||||
|      | ||||
|     my $mesh = Slic3r::TriangleMesh->new(facets => [], vertices => []); | ||||
|     for my $obj_idx (0 .. $#{$print->objects}) { | ||||
|         for my $copy (@{$print->copies->[$obj_idx]}) { | ||||
|             my $cloned_mesh = $print->objects->[$obj_idx]->mesh->clone; | ||||
|             $cloned_mesh->move(@$copy); | ||||
|             my $vertices_offset = scalar @{$mesh->vertices}; | ||||
|             push @{$mesh->vertices}, @{$cloned_mesh->vertices}; | ||||
|             push @{$mesh->facets}, map [ $_->[0], map $vertices_offset + $_, @$_[-3..-1] ], @{$cloned_mesh->facets}; | ||||
|         } | ||||
|     } | ||||
|     $mesh->scale(&Slic3r::SCALING_FACTOR); | ||||
|     $mesh->align_to_origin; | ||||
|      | ||||
|     Slic3r::Format::STL->write_file($output_file, $mesh, 1); | ||||
|     Slic3r::Format::STL->write_file($output_file, $self->make_model, binary => 1); | ||||
|     $self->statusbar->SetStatusText("STL file exported to $output_file"); | ||||
| } | ||||
| 
 | ||||
| sub make_model { | ||||
|     my $self = shift; | ||||
|      | ||||
|     my $model = Slic3r::Model->new; | ||||
|     for my $obj_idx (0 .. $#{$self->{print}->objects}) { | ||||
|         my $mesh = $self->{print}->objects->[$obj_idx]->mesh->clone; | ||||
|         $mesh->scale(&Slic3r::SCALING_FACTOR); | ||||
|         my $object = $model->add_object(vertices => $mesh->vertices); | ||||
|         $object->add_volume(facets => $mesh->facets); | ||||
|         for my $copy (@{$self->{print}->copies->[$obj_idx]}) { | ||||
|             $object->add_instance(rotation => 0, offset => [ map unscale $_, @$copy ]); | ||||
|         } | ||||
|     } | ||||
|     # TODO: $model->align_to_origin; | ||||
|      | ||||
|     return $model; | ||||
| } | ||||
| 
 | ||||
| sub make_thumbnail { | ||||
|     my $self = shift; | ||||
|     my ($obj_idx) = @_; | ||||
|  |  | |||
|  | @ -96,7 +96,7 @@ sub do_slice { | |||
|         Slic3r::GUI->save_settings; | ||||
|          | ||||
|         my $print = Slic3r::Print->new(config => $config); | ||||
|         $print->add_object_from_file($input_file); | ||||
|         $print->add_objects_from_file($input_file); | ||||
|         $print->validate; | ||||
| 
 | ||||
|         # select output file | ||||
|  |  | |||
							
								
								
									
										112
									
								
								lib/Slic3r/Model.pm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								lib/Slic3r/Model.pm
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | |||
| package Slic3r::Model; | ||||
| use Moo; | ||||
| 
 | ||||
| use Slic3r::Geometry qw(X Y Z); | ||||
| 
 | ||||
| has 'materials' => (is => 'ro', default => sub { [] }); | ||||
| has 'objects'   => (is => 'ro', default => sub { [] }); | ||||
| 
 | ||||
| sub add_object { | ||||
|     my $self = shift; | ||||
|      | ||||
|     my $object = Slic3r::Model::Object->new(model => $self, @_); | ||||
|     push @{$self->objects}, $object; | ||||
|     return $object; | ||||
| } | ||||
| 
 | ||||
| # flattens everything to a single mesh | ||||
| sub mesh { | ||||
|     my $self = shift; | ||||
|      | ||||
|     my $vertices = []; | ||||
|     my $facets = []; | ||||
|     foreach my $object (@{$self->objects}) { | ||||
|         my @instances = $object->instances ? @{$object->instances} : (undef); | ||||
|         foreach my $instance (@instances) { | ||||
|             my @vertices = @{$object->vertices}; | ||||
|             if ($instance) { | ||||
|                 # save Z coordinates, as rotation and translation discard them | ||||
|                 my @z = map $_->[Z], @vertices; | ||||
|                  | ||||
|                 if ($instance->rotation) { | ||||
|                     # transform vertex coordinates | ||||
|                     my $rad = Slic3r::Geometry::deg2rad($instance->rotation); | ||||
|                     @vertices = Slic3r::Geometry::rotate_points($rad, undef, @vertices); | ||||
|                 } | ||||
|                 @vertices = Slic3r::Geometry::move_points($instance->offset, @vertices); | ||||
|                  | ||||
|                 # reapply Z coordinates | ||||
|                 $vertices[$_][Z] = $z[$_] for 0 .. $#z; | ||||
|             } | ||||
|              | ||||
|             my $v_offset = @$vertices; | ||||
|             push @$vertices, @vertices; | ||||
|             foreach my $volume (@{$object->volumes}) { | ||||
|                 push @$facets, map { | ||||
|                     my $f = [@$_]; | ||||
|                     $f->[$_] += $v_offset for -3..-1; | ||||
|                     $f; | ||||
|                 } @{$volume->facets}; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return Slic3r::TriangleMesh->new( | ||||
|         vertices => $vertices, | ||||
|         facets   => $facets, | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| package Slic3r::Model::Material; | ||||
| use Moo; | ||||
| 
 | ||||
| has 'model'         => (is => 'ro', weak_ref => 1, required => 1); | ||||
| has 'attributes'    => (is => 'rw', default => sub { {} }); | ||||
| 
 | ||||
| package Slic3r::Model::Object; | ||||
| use Moo; | ||||
| 
 | ||||
| has 'model'     => (is => 'ro', weak_ref => 1, required => 1); | ||||
| has 'vertices'  => (is => 'ro', default => sub { [] }); | ||||
| has 'volumes'   => (is => 'ro', default => sub { [] }); | ||||
| has 'instances' => (is => 'rw'); | ||||
| 
 | ||||
| sub add_volume { | ||||
|     my $self = shift; | ||||
|      | ||||
|     my $volume = Slic3r::Model::Volume->new(object => $self, @_); | ||||
|     push @{$self->volumes}, $volume; | ||||
|     return $volume; | ||||
| } | ||||
| 
 | ||||
| sub add_instance { | ||||
|     my $self = shift; | ||||
|      | ||||
|     $self->instances([]) if !defined $self->instances; | ||||
|     push @{$self->instances}, Slic3r::Model::Instance->new(object => $self, @_); | ||||
|     return $self->instances->[-1]; | ||||
| } | ||||
| 
 | ||||
| package Slic3r::Model::Volume; | ||||
| use Moo; | ||||
| 
 | ||||
| has 'object'        => (is => 'ro', weak_ref => 1, required => 1); | ||||
| has 'material_id'   => (is => 'rw'); | ||||
| has 'facets'        => (is => 'rw', default => sub { [] }); | ||||
| 
 | ||||
| sub mesh { | ||||
|     my $self = shift; | ||||
|     return Slic3r::TriangleMesh->new( | ||||
|         vertices => $self->object->vertices, | ||||
|         facets   => $self->facets, | ||||
|     ); | ||||
| } | ||||
| 
 | ||||
| package Slic3r::Model::Instance; | ||||
| use Moo; | ||||
| 
 | ||||
| has 'object'    => (is => 'ro', weak_ref => 1, required => 1); | ||||
| has 'rotation'  => (is => 'rw', default => sub { 0 }); | ||||
| has 'offset'    => (is => 'rw'); | ||||
| 
 | ||||
| 1; | ||||
|  | @ -79,28 +79,43 @@ sub _trigger_config { | |||
|     $self->config->set_ifndef('top_solid_infill_speed', $self->config->solid_infill_speed); | ||||
| } | ||||
| 
 | ||||
| sub add_object_from_file { | ||||
| sub add_objects_from_file { | ||||
|     my $self = shift; | ||||
|     my ($input_file) = @_; | ||||
|      | ||||
|     my $object; | ||||
|     if ($input_file =~ /\.stl$/i) { | ||||
|         my $mesh = Slic3r::Format::STL->read_file($input_file); | ||||
|         $mesh->check_manifoldness; | ||||
|         $object = $self->add_object_from_mesh($mesh); | ||||
|     } elsif ($input_file =~ /\.obj$/i) { | ||||
|         my $mesh = Slic3r::Format::OBJ->read_file($input_file); | ||||
|         $mesh->check_manifoldness; | ||||
|         $object = $self->add_object_from_mesh($mesh); | ||||
|     } elsif ( $input_file =~ /\.amf(\.xml)?$/i) { | ||||
|         my ($materials, $meshes_by_material) = Slic3r::Format::AMF->read_file($input_file); | ||||
|         $_->check_manifoldness for values %$meshes_by_material; | ||||
|         $object = $self->add_object_from_mesh($meshes_by_material->{_} || +(values %$meshes_by_material)[0]); | ||||
|     } else { | ||||
|         die "Input file must have .stl, .obj or .amf(.xml) extension\n"; | ||||
|     my $model = $input_file =~ /\.stl$/i            ? Slic3r::Format::STL->read_file($input_file) | ||||
|               : $input_file =~ /\.obj$/i            ? Slic3r::Format::OBJ->read_file($input_file) | ||||
|               : $input_file =~ /\.amf(\.xml)?$/i    ? Slic3r::Format::AMF->read_file($input_file) | ||||
|               : die "Input file must have .stl, .obj or .amf(.xml) extension\n"; | ||||
|      | ||||
|     my @print_objects = $self->add_model($model); | ||||
|     $_->input_file($input_file) for @print_objects; | ||||
| } | ||||
|     $object->input_file($input_file); | ||||
|     return $object; | ||||
| 
 | ||||
| sub add_model { | ||||
|     my $self = shift; | ||||
|     my ($model) = @_; | ||||
|      | ||||
|     my @print_objects = (); | ||||
|     foreach my $object (@{ $model->objects }) { | ||||
|         my $mesh = $object->volumes->[0]->mesh; | ||||
|         $mesh->check_manifoldness; | ||||
|          | ||||
|         if ($object->instances) { | ||||
|             # we ignore the per-instance rotation currently and only  | ||||
|             # consider the first one | ||||
|             $mesh->rotate($object->instances->[0]->rotation); | ||||
|         } | ||||
|          | ||||
|         push @print_objects, $self->add_object_from_mesh($mesh); | ||||
|          | ||||
|         if ($object->instances) { | ||||
|             # replace the default [0,0] instance with the custom ones | ||||
|             @{$self->copies->[-1]} = map [ scale $_->offset->[X], scale $_->offset->[X] ], @{$object->instances}; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     return @print_objects; | ||||
| } | ||||
| 
 | ||||
| sub add_object_from_mesh { | ||||
|  |  | |||
|  | @ -88,9 +88,9 @@ if (@ARGV) {  # slicing from command line | |||
|      | ||||
|     while (my $input_file = shift @ARGV) { | ||||
|         my $print = Slic3r::Print->new(config => $config); | ||||
|         $print->add_object_from_file($input_file); | ||||
|         $print->add_objects_from_file($input_file); | ||||
|         if ($opt{merge}) { | ||||
|             $print->add_object_from_file($_) for splice @ARGV, 0; | ||||
|             $print->add_objects_from_file($_) for splice @ARGV, 0; | ||||
|         } | ||||
|         $print->duplicate; | ||||
|         $print->arrange_objects if @{$print->objects} > 1; | ||||
|  |  | |||
|  | @ -25,12 +25,12 @@ my %opt = (); | |||
| } | ||||
| 
 | ||||
| { | ||||
|     my $mesh = Slic3r::Format::AMF->read_file($ARGV[0]); | ||||
|     my $model = Slic3r::Format::AMF->read_file($ARGV[0]); | ||||
|     my $output_file = $ARGV[0]; | ||||
|     $output_file =~ s/\.amf(?:\.xml)?$/\.stl/i; | ||||
|      | ||||
|     printf "Writing to %s\n", basename($output_file); | ||||
|     Slic3r::Format::STL->write_file($output_file, $mesh, !$opt{ascii}); | ||||
|     Slic3r::Format::STL->write_file($output_file, $model, binary => !$opt{ascii}); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,15 +25,20 @@ my %opt = (); | |||
| } | ||||
| 
 | ||||
| { | ||||
|     my $mesh = Slic3r::Format::STL->read_file($ARGV[0]); | ||||
|     my $model = Slic3r::Format::STL->read_file($ARGV[0]); | ||||
|     my $basename = $ARGV[0]; | ||||
|     $basename =~ s/\.stl$//i; | ||||
|      | ||||
|     my $part_count = 0; | ||||
|     foreach my $new_mesh ($mesh->split_mesh) { | ||||
|     foreach my $new_mesh ($model->mesh->split_mesh) { | ||||
|         my $new_model = Slic3r::Model->new; | ||||
|         $new_model | ||||
|             ->add_object(vertices   => $new_mesh->vertices) | ||||
|             ->add_volume(facets     => $new_mesh->facets); | ||||
|          | ||||
|         my $output_file = sprintf '%s_%02d.stl', $basename, ++$part_count; | ||||
|         printf "Writing to %s\n", basename($output_file); | ||||
|         Slic3r::Format::STL->write_file($output_file, $new_mesh, !$opt{ascii}); | ||||
|         Slic3r::Format::STL->write_file($output_file, $new_model, binary => !$opt{ascii}); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,29 +18,49 @@ my %opt = (); | |||
| { | ||||
|     my %options = ( | ||||
|         'help'                  => sub { usage() }, | ||||
|         'distinct-materials'    => \$opt{distinct_materials}, | ||||
|     ); | ||||
|     GetOptions(%options) or usage(1); | ||||
|     $ARGV[0] or usage(1); | ||||
| } | ||||
| 
 | ||||
| { | ||||
|     my @meshes = map Slic3r::Format::STL->read_file($_), @ARGV; | ||||
|     my @models = map Slic3r::Format::STL->read_file($_), @ARGV; | ||||
|     my $output_file = $ARGV[0]; | ||||
|     $output_file =~ s/\.stl$/.amf.xml/i; | ||||
|      | ||||
|     my $materials = {}; | ||||
|     my $meshes_by_material = {}; | ||||
|     if (@meshes == 1) { | ||||
|         $meshes_by_material->{_} = $meshes[0]; | ||||
|     my $new_model = Slic3r::Model->new; | ||||
|      | ||||
|     if ($opt{distinct_materials} && @models > 1) { | ||||
|         my $new_object = $new_model->add_object; | ||||
|         for my $m (0 .. $#models) { | ||||
|             my $model = $models[$m]; | ||||
|             my $v_offset = @{$new_object->vertices}; | ||||
|             push @{$new_object->vertices}, @{$model->objects->[0]->vertices}; | ||||
|             my @new_facets = map { | ||||
|                 my $f = [@$_]; | ||||
|                 $f->[$_] += $v_offset for -3..-1; | ||||
|                 $f; | ||||
|             } @{ $model->objects->[0]->volumes->[0]->facets }; | ||||
|              | ||||
|             push @{$new_model->materials}, { Name => basename($ARGV[$m]) }; | ||||
|             $new_object->add_volume( | ||||
|                 material_id => $#{$new_model->materials}, | ||||
|                 facets      => [@new_facets], | ||||
|             ); | ||||
|         } | ||||
|     } else { | ||||
|         for (0..$#meshes) { | ||||
|             $materials->{$_+1} = { Name => basename($ARGV[$_]) }; | ||||
|             $meshes_by_material->{$_+1} = $meshes[$_]; | ||||
|         foreach my $model (@models) { | ||||
|             $new_model->add_object( | ||||
|                 vertices => $model->objects->[0]->vertices, | ||||
|             )->add_volume( | ||||
|                 facets => $model->objects->[0]->volumes->[0]->facets, | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     printf "Writing to %s\n", basename($output_file); | ||||
|     Slic3r::Format::AMF->write_file($output_file, $materials, $meshes_by_material); | ||||
|     Slic3r::Format::AMF->write_file($output_file, $new_model); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -51,6 +71,7 @@ sub usage { | |||
| Usage: amf-to-stl.pl [ OPTIONS ] file.stl [ file2.stl [ file3.stl ] ] | ||||
| 
 | ||||
|     --help              Output this usage screen and exit | ||||
|     --distinct-materials Assign each STL file to a different material | ||||
|      | ||||
| EOF | ||||
|     exit ($exit_code || 0); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Alessandro Ranellucci
						Alessandro Ranellucci