Initial work for new model handling
This commit is contained in:
parent
57fd6ad563
commit
7871673bf6
3 changed files with 89 additions and 66 deletions
|
@ -130,6 +130,16 @@ sub min_point {
|
||||||
return Slic3r::Point->new($self->extents->[X][MIN], $self->extents->[Y][MIN]);
|
return Slic3r::Point->new($self->extents->[X][MIN], $self->extents->[Y][MIN]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub min_point3 {
|
||||||
|
my $self = shift;
|
||||||
|
return [ map $self->extents->[$_][MIN], (X,Y,Z) ];
|
||||||
|
}
|
||||||
|
|
||||||
|
sub vector_to_origin {
|
||||||
|
my $self = shift;
|
||||||
|
return [ map -$_, @{$self->min_point3} ];
|
||||||
|
}
|
||||||
|
|
||||||
sub max_point {
|
sub max_point {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
return Slic3r::Point->new($self->extents->[X][MAX], $self->extents->[Y][MAX]);
|
return Slic3r::Point->new($self->extents->[X][MAX], $self->extents->[Y][MAX]);
|
||||||
|
|
|
@ -77,9 +77,9 @@ sub _build_has_support_material {
|
||||||
|
|
||||||
# caller is responsible for supplying models whose objects don't collide
|
# caller is responsible for supplying models whose objects don't collide
|
||||||
# and have explicit instance positions
|
# and have explicit instance positions
|
||||||
sub add_model {
|
sub add_model_object {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my ($model) = @_;
|
my ($object) = @_;
|
||||||
|
|
||||||
# optimization: if avoid_crossing_perimeters is enabled, split
|
# optimization: if avoid_crossing_perimeters is enabled, split
|
||||||
# this mesh into distinct objects so that we reduce the complexity
|
# this mesh into distinct objects so that we reduce the complexity
|
||||||
|
@ -90,76 +90,89 @@ sub add_model {
|
||||||
# -- thing before the split.
|
# -- thing before the split.
|
||||||
###$model->split_meshes if $Slic3r::Config->avoid_crossing_perimeters && !$Slic3r::Config->complete_objects;
|
###$model->split_meshes if $Slic3r::Config->avoid_crossing_perimeters && !$Slic3r::Config->complete_objects;
|
||||||
|
|
||||||
my %unmapped_materials = ();
|
# read the material mapping provided by the model object, if any
|
||||||
foreach my $object (@{ $model->objects }) {
|
my %matmap = %{ $object->material_mapping || {} };
|
||||||
# we align object to origin before applying transformations
|
$_-- for values %matmap; # extruders in the mapping are 1-indexed but we want 0-indexed
|
||||||
my @align = $object->align_to_origin;
|
|
||||||
|
my %meshes = (); # region_id => TriangleMesh
|
||||||
# extract meshes by material
|
foreach my $volume (@{$object->volumes}) {
|
||||||
my @meshes = (); # by region_id
|
my $region_id;
|
||||||
foreach my $volume (@{$object->volumes}) {
|
if (defined $volume->material_id) {
|
||||||
my $region_id;
|
if (!exists $matmap{ $volume->material_id }) {
|
||||||
if (defined $volume->material_id) {
|
# there's no mapping between this material and a region
|
||||||
if ($object->material_mapping) {
|
$matmap{ $volume->material_id } = scalar(@{ $self->regions });
|
||||||
$region_id = $object->material_mapping->{$volume->material_id} - 1
|
|
||||||
if defined $object->material_mapping->{$volume->material_id};
|
|
||||||
}
|
|
||||||
$region_id //= $unmapped_materials{$volume->material_id};
|
|
||||||
if (!defined $region_id) {
|
|
||||||
$region_id = $unmapped_materials{$volume->material_id} = scalar(keys %unmapped_materials);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
$region_id //= 0;
|
$region_id = $matmap{ $volume->material_id };
|
||||||
|
} else {
|
||||||
my $mesh = $volume->mesh->clone;
|
$region_id = 0;
|
||||||
# should the object contain multiple volumes of the same material, merge them
|
|
||||||
$meshes[$region_id] = $meshes[$region_id]
|
|
||||||
? Slic3r::TriangleMesh->merge($meshes[$region_id], $mesh)
|
|
||||||
: $mesh;
|
|
||||||
}
|
|
||||||
$self->regions->[$_] //= Slic3r::Print::Region->new for 0..$#meshes;
|
|
||||||
|
|
||||||
foreach my $mesh (grep $_, @meshes) {
|
|
||||||
# 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_2D);
|
|
||||||
$mesh->scale($object->instances->[0]->scaling_factor);
|
|
||||||
}
|
|
||||||
$mesh->repair;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# we also align object after transformations so that we only work with positive coordinates
|
# instantiate region if it does not exist
|
||||||
# and the assumption that bounding_box === size works
|
$self->regions->[$region_id] //= Slic3r::Print::Region->new;
|
||||||
my $bb = Slic3r::Geometry::BoundingBox->merge(map $_->bounding_box, grep $_, @meshes);
|
|
||||||
my @align2 = map -$bb->extents->[$_][MIN], (X,Y,Z);
|
|
||||||
$_->translate(@align2) for grep $_, @meshes;
|
|
||||||
|
|
||||||
my $scaled_bb = $bb->clone;
|
# if a mesh is already associated to this region, append this one to it
|
||||||
$scaled_bb->scale(1 / &Slic3r::SCALING_FACTOR);
|
$meshes{$region_id} //= Slic3r::TriangleMesh->new;
|
||||||
|
$meshes{$region_id}->merge($volume->mesh);
|
||||||
# initialize print object
|
|
||||||
push @{$self->objects}, Slic3r::Print::Object->new(
|
|
||||||
print => $self,
|
|
||||||
meshes => [ @meshes ],
|
|
||||||
copies => [
|
|
||||||
map Slic3r::Point->new(@$_),
|
|
||||||
$object->instances
|
|
||||||
? (map [ scale($_->offset->[X] - $align[X]) - $align2[X], scale($_->offset->[Y] - $align[Y]) - $align2[Y] ], @{$object->instances})
|
|
||||||
: [0,0],
|
|
||||||
],
|
|
||||||
size => $scaled_bb->size, # transformed size
|
|
||||||
input_file => $object->input_file,
|
|
||||||
config_overrides => $object->config,
|
|
||||||
layer_height_ranges => $object->layer_height_ranges,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $bb1 = Slic3r::Geometry::BoundingBox->merge(map $_->bounding_box, values %meshes);
|
||||||
|
|
||||||
|
foreach my $mesh (values %meshes) {
|
||||||
|
# align meshes to origin before applying transformations
|
||||||
|
$mesh->translate(@{$bb1->vector_to_origin});
|
||||||
|
|
||||||
|
# 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_2D);
|
||||||
|
$mesh->scale($object->instances->[0]->scaling_factor);
|
||||||
|
}
|
||||||
|
$mesh->repair;
|
||||||
|
}
|
||||||
|
|
||||||
|
# we align object also after transformations so that we only work with positive coordinates
|
||||||
|
# and the assumption that bounding_box === size works
|
||||||
|
my $bb2 = Slic3r::Geometry::BoundingBox->merge(map $_->bounding_box, values %meshes);
|
||||||
|
$_->translate(@{$bb2->vector_to_origin}) for values %meshes;
|
||||||
|
|
||||||
|
# prepare scaled object size
|
||||||
|
my $scaled_bb = $bb2->clone;
|
||||||
|
$scaled_bb->translate(@{$bb2->vector_to_origin}); # not needed for getting size, but who knows
|
||||||
|
$scaled_bb->scale(1 / &Slic3r::SCALING_FACTOR);
|
||||||
|
|
||||||
|
# prepare copies
|
||||||
|
my @copies = ();
|
||||||
|
if ($object->instances) {
|
||||||
|
foreach my $instance (@{ $object->instances }) {
|
||||||
|
push @copies, Slic3r::Point->new(
|
||||||
|
scale($instance->offset->[X] - $bb1->extents->[X][MIN])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
push @copies, Slic3r::Point->new(0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
# initialize print object
|
||||||
|
push @{$self->objects}, Slic3r::Print::Object->new(
|
||||||
|
print => $self,
|
||||||
|
meshes => [ map $meshes{$_}, 0..$#{$self->regions} ],
|
||||||
|
copies => [
|
||||||
|
map Slic3r::Point->new(@$_),
|
||||||
|
$object->instances
|
||||||
|
? (map [ scale($_->offset->[X] - $align[X]) - $align2[X], scale($_->offset->[Y] - $align[Y]) - $align2[Y] ], @{$object->instances})
|
||||||
|
: [0,0],
|
||||||
|
],
|
||||||
|
size => $scaled_bb->size, # transformed size
|
||||||
|
input_file => $object->input_file,
|
||||||
|
config_overrides => $object->config,
|
||||||
|
layer_height_ranges => $object->layer_height_ranges,
|
||||||
|
);
|
||||||
|
|
||||||
if (!defined $self->extra_variables->{input_filename}) {
|
if (!defined $self->extra_variables->{input_filename}) {
|
||||||
if (defined (my $input_file = $self->objects->[0]->input_file)) {
|
if (defined (my $input_file = $object->input_file)) {
|
||||||
@{$self->extra_variables}{qw(input_filename input_filename_base)} = parse_filename($input_file);
|
@{$self->extra_variables}{qw(input_filename input_filename_base)} = parse_filename($input_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ if (@ARGV) { # slicing from command line
|
||||||
}
|
}
|
||||||
|
|
||||||
my $print = Slic3r::Print->new(config => $config);
|
my $print = Slic3r::Print->new(config => $config);
|
||||||
$print->add_model($model);
|
$print->add_model_object($_) for @{$model->objects};
|
||||||
$print->validate;
|
$print->validate;
|
||||||
my %params = (
|
my %params = (
|
||||||
output_file => $opt{output},
|
output_file => $opt{output},
|
||||||
|
|
Loading…
Add table
Reference in a new issue