2012-02-25 16:35:25 +00:00
|
|
|
package Slic3r::Format::AMF;
|
2012-02-19 14:14:54 +00:00
|
|
|
use Moo;
|
2012-02-19 14:45:27 +00:00
|
|
|
|
|
|
|
use Slic3r::Geometry qw(X Y Z);
|
2012-02-19 14:14:54 +00:00
|
|
|
|
|
|
|
sub read_file {
|
|
|
|
my $self = shift;
|
|
|
|
my ($file) = @_;
|
|
|
|
|
2012-10-24 18:36:32 +00:00
|
|
|
eval qq{
|
|
|
|
require Slic3r::Format::AMF::Parser;
|
|
|
|
use XML::SAX::ParserFactory;
|
|
|
|
1;
|
|
|
|
} or die "AMF parsing requires XML::SAX\n";
|
2012-02-19 14:14:54 +00:00
|
|
|
|
2013-01-13 09:18:34 +00:00
|
|
|
Slic3r::open(\my $fh, '<', $file) or die "Failed to open $file\n";
|
2012-02-19 14:14:54 +00:00
|
|
|
|
2012-08-29 16:23:34 +00:00
|
|
|
my $model = Slic3r::Model->new;
|
2012-10-24 18:36:32 +00:00
|
|
|
XML::SAX::ParserFactory
|
|
|
|
->parser(Handler => Slic3r::Format::AMF::Parser->new(_model => $model))
|
2012-02-19 14:14:54 +00:00
|
|
|
->parse_file($fh);
|
|
|
|
close $fh;
|
|
|
|
|
2012-08-29 14:49:38 +00:00
|
|
|
return $model;
|
2012-02-19 14:14:54 +00:00
|
|
|
}
|
|
|
|
|
2012-02-19 14:45:27 +00:00
|
|
|
sub write_file {
|
|
|
|
my $self = shift;
|
2012-08-29 14:49:38 +00:00
|
|
|
my ($file, $model, %params) = @_;
|
2012-02-20 15:43:45 +00:00
|
|
|
|
|
|
|
my %vertices_offset = ();
|
2012-02-19 14:45:27 +00:00
|
|
|
|
2013-01-13 09:18:34 +00:00
|
|
|
Slic3r::open(\my $fh, '>', $file);
|
2012-02-19 14:45:27 +00:00
|
|
|
binmode $fh, ':utf8';
|
|
|
|
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;
|
2012-08-29 16:23:34 +00:00
|
|
|
for my $material_id (sort keys %{ $model->materials }) {
|
|
|
|
my $material = $model->materials->{$material_id};
|
2014-02-14 23:36:52 +00:00
|
|
|
printf $fh qq{ <material id="%s">\n}, $material_id;
|
2012-09-22 17:04:36 +00:00
|
|
|
for (keys %{$material->attributes}) {
|
|
|
|
printf $fh qq{ <metadata type=\"%s\">%s</metadata>\n}, $_, $material->attributes->{$_};
|
2012-02-20 15:43:45 +00:00
|
|
|
}
|
2014-02-14 23:36:52 +00:00
|
|
|
my $config = $material->config;
|
|
|
|
foreach my $opt_key (@{$config->get_keys}) {
|
|
|
|
printf $fh qq{ <metadata type=\"slic3r.%s\">%s</metadata>\n}, $opt_key, $config->serialize($opt_key);
|
|
|
|
}
|
2012-02-20 15:43:45 +00:00
|
|
|
printf $fh qq{ </material>\n};
|
|
|
|
}
|
2012-08-29 15:11:56 +00:00
|
|
|
my $instances = '';
|
2012-08-29 14:49:38 +00:00
|
|
|
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};
|
2013-09-16 07:58:09 +00:00
|
|
|
my @vertices_offset = ();
|
|
|
|
{
|
|
|
|
my $vertices_offset = 0;
|
|
|
|
foreach my $volume (@{ $object->volumes }) {
|
|
|
|
push @vertices_offset, $vertices_offset;
|
|
|
|
my $vertices = $volume->mesh->vertices;
|
|
|
|
foreach my $vertex (@$vertices) {
|
|
|
|
printf $fh qq{ <vertex>\n};
|
|
|
|
printf $fh qq{ <coordinates>\n};
|
|
|
|
printf $fh qq{ <x>%s</x>\n}, $vertex->[X];
|
|
|
|
printf $fh qq{ <y>%s</y>\n}, $vertex->[Y];
|
|
|
|
printf $fh qq{ <z>%s</z>\n}, $vertex->[Z];
|
|
|
|
printf $fh qq{ </coordinates>\n};
|
|
|
|
printf $fh qq{ </vertex>\n};
|
|
|
|
}
|
|
|
|
$vertices_offset += scalar(@$vertices);
|
|
|
|
}
|
2012-02-20 15:43:45 +00:00
|
|
|
}
|
2012-08-29 14:49:38 +00:00
|
|
|
printf $fh qq{ </vertices>\n};
|
|
|
|
foreach my $volume (@{ $object->volumes }) {
|
2013-09-16 07:58:09 +00:00
|
|
|
my $vertices_offset = shift @vertices_offset;
|
2012-08-29 14:49:38 +00:00
|
|
|
printf $fh qq{ <volume%s>\n},
|
|
|
|
(!defined $volume->material_id) ? '' : (sprintf ' materialid="%s"', $volume->material_id);
|
2013-09-16 07:58:09 +00:00
|
|
|
foreach my $facet (@{$volume->mesh->facets}) {
|
2012-08-29 14:49:38 +00:00
|
|
|
printf $fh qq{ <triangle>\n};
|
2013-09-16 07:58:09 +00:00
|
|
|
printf $fh qq{ <v%d>%d</v%d>\n}, $_, $facet->[$_-1] + $vertices_offset, $_ for 1..3;
|
2012-08-29 14:49:38 +00:00
|
|
|
printf $fh qq{ </triangle>\n};
|
|
|
|
}
|
|
|
|
printf $fh qq{ </volume>\n};
|
2012-02-20 15:43:45 +00:00
|
|
|
}
|
2012-08-29 14:49:38 +00:00
|
|
|
printf $fh qq{ </mesh>\n};
|
|
|
|
printf $fh qq{ </object>\n};
|
2012-08-29 15:11:56 +00:00
|
|
|
if ($object->instances) {
|
|
|
|
foreach my $instance (@{$object->instances}) {
|
|
|
|
$instances .= sprintf qq{ <instance objectid="%d">\n}, $object_id;
|
|
|
|
$instances .= sprintf qq{ <deltax>%s</deltax>\n}, $instance->offset->[X];
|
2012-09-12 14:30:44 +00:00
|
|
|
$instances .= sprintf qq{ <deltay>%s</deltay>\n}, $instance->offset->[Y];
|
2012-08-29 15:11:56 +00:00
|
|
|
$instances .= sprintf qq{ <rz>%s</rz>\n}, $instance->rotation;
|
|
|
|
$instances .= sprintf qq{ </instance>\n};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($instances) {
|
|
|
|
printf $fh qq{ <constellation id="1">\n};
|
|
|
|
printf $fh $instances;
|
|
|
|
printf $fh qq{ </constellation>\n};
|
2012-02-19 14:45:27 +00:00
|
|
|
}
|
|
|
|
printf $fh qq{</amf>\n};
|
|
|
|
close $fh;
|
|
|
|
}
|
|
|
|
|
2012-02-19 14:14:54 +00:00
|
|
|
1;
|