Incomplete work to store TriangleMesh objects in Model objects instead of extracting vertices and facets

This commit is contained in:
Alessandro Ranellucci 2013-09-11 09:49:28 +02:00
parent 78ee6e5d6d
commit 11e18f681d
8 changed files with 45 additions and 100 deletions

View File

@ -1,20 +1,17 @@
package Slic3r::Format::STL; package Slic3r::Format::STL;
use Moo; use Moo;
use Slic3r::Geometry qw(X Y Z triangle_normal);
sub read_file { sub read_file {
my $self = shift; my $self = shift;
my ($file) = @_; my ($file) = @_;
my $tmesh = Slic3r::TriangleMesh->new; my $mesh = Slic3r::TriangleMesh->new;
$tmesh->ReadSTLFile(Slic3r::encode_path($file)); $mesh->ReadSTLFile(Slic3r::encode_path($file));
$tmesh->repair; $mesh->repair;
my ($vertices, $facets) = ($tmesh->vertices, $tmesh->facets);
my $model = Slic3r::Model->new; my $model = Slic3r::Model->new;
my $object = $model->add_object(vertices => $vertices, mesh_stats => $tmesh->stats); my $object = $model->add_object;
my $volume = $object->add_volume(facets => $facets); my $volume = $object->add_volume(mesh => $mesh);
return $model; return $model;
} }
@ -22,48 +19,11 @@ sub write_file {
my $self = shift; my $self = shift;
my ($file, $model, %params) = @_; my ($file, $model, %params) = @_;
Slic3r::open(\my $fh, '>', $file); my $path = Slic3r::encode_path($file);
$params{binary} $params{binary}
? _write_binary($fh, $model->mesh) ? $model->mesh->write_binary($path)
: _write_ascii($fh, $model->mesh); : $model->mesh->write_ascii($path);
close $fh;
}
sub _write_binary {
my ($fh, $mesh) = @_;
die "bigfloat" unless length(pack "f", 1) == 4;
binmode $fh;
print $fh pack 'x80';
print $fh pack 'L', scalar(@{$mesh->facets});
foreach my $facet (@{$mesh->facets}) {
print $fh pack '(f<3)4S',
@{_facet_normal($mesh, $facet)},
(map @{$mesh->vertices->[$_]}, @$facet[-3..-1]),
0;
}
}
sub _write_ascii {
my ($fh, $mesh) = @_;
printf $fh "solid\n";
foreach my $facet (@{$mesh->facets}) {
printf $fh " facet normal %f %f %f\n", @{_facet_normal($mesh, $facet)};
printf $fh " outer loop\n";
printf $fh " vertex %f %f %f\n", @{$mesh->vertices->[$_]} for @$facet[-3..-1];
printf $fh " endloop\n";
printf $fh " endfacet\n";
}
printf $fh "endsolid\n";
}
sub _facet_normal {
my ($mesh, $facet) = @_;
return triangle_normal(map $mesh->vertices->[$_], @$facet[-3..-1]);
} }
1; 1;

View File

@ -315,32 +315,21 @@ use Storable qw(dclone);
has 'input_file' => (is => 'rw'); has 'input_file' => (is => 'rw');
has 'model' => (is => 'ro', weak_ref => 1, required => 1); has 'model' => (is => 'ro', weak_ref => 1, required => 1);
has 'vertices' => (is => 'ro', default => sub { [] });
has 'volumes' => (is => 'ro', default => sub { [] }); has 'volumes' => (is => 'ro', default => sub { [] });
has 'instances' => (is => 'rw'); has 'instances' => (is => 'rw');
has 'config' => (is => 'rw', default => sub { Slic3r::Config->new }); has 'config' => (is => 'rw', default => sub { Slic3r::Config->new });
has 'layer_height_ranges' => (is => 'rw', default => sub { [] }); # [ z_min, z_max, layer_height ] has 'layer_height_ranges' => (is => 'rw', default => sub { [] }); # [ z_min, z_max, layer_height ]
has 'material_mapping' => (is => 'rw', default => sub { {} }); # { material_id => extruder_idx } has 'material_mapping' => (is => 'rw', default => sub { {} }); # { material_id => extruder_idx }
has 'mesh_stats' => (is => 'rw');
has '_bounding_box' => (is => 'rw'); has '_bounding_box' => (is => 'rw');
sub add_volume { sub add_volume {
my $self = shift; my $self = shift;
my %args = @_; my %args = @_;
if (my $vertices = delete $args{vertices}) { push @{$self->volumes}, my $volume = Slic3r::Model::Volume->new(
my $v_offset = @{$self->vertices}; object => $self,
push @{$self->vertices}, @$vertices; %args,
);
@{$args{facets}} = map {
my $f = [@$_];
$f->[$_] += $v_offset for -3..-1;
$f;
} @{$args{facets}};
}
my $volume = Slic3r::Model::Volume->new(object => $self, %args);
push @{$self->volumes}, $volume;
$self->_bounding_box(undef); $self->_bounding_box(undef);
$self->model->_bounding_box(undef); $self->model->_bounding_box(undef);
return $volume; return $volume;
@ -358,16 +347,14 @@ sub add_instance {
sub mesh { sub mesh {
my $self = shift; my $self = shift;
# this mesh won't be suitable for check_manifoldness as multiple
# facets from different volumes may use the same vertices
my $mesh = Slic3r::TriangleMesh->new; my $mesh = Slic3r::TriangleMesh->new;
$mesh->ReadFromPerl($self->vertices, [ map @{$_->facets}, @{$self->volumes} ]); $mesh->merge($_->mesh) for @{$self->volumes};
return $mesh; return $mesh;
} }
sub used_vertices { sub used_vertices {
my $self = shift; my $self = shift;
return [ map $self->vertices->[$_], map @$_, map @{$_->facets}, @{$self->volumes} ]; return [ map $_->mesh->used_vertices, @{$self->volumes} ];
} }
sub size { sub size {
@ -389,7 +376,8 @@ sub bounding_box {
my $self = shift; my $self = shift;
if (!defined $self->_bounding_box) { if (!defined $self->_bounding_box) {
$self->_bounding_box(Slic3r::Geometry::BoundingBox->new_from_points_3D($self->used_vertices)); # TODO: calculate bb in XS
$self->_bounding_box(Slic3r::Geometry::BoundingBox->new_from_points_3D(map $_->mesh->vertices, @{$self->volumes}));
} }
return $self->_bounding_box; return $self->_bounding_box;
} }
@ -409,7 +397,7 @@ sub move {
my $self = shift; my $self = shift;
my @shift = @_; my @shift = @_;
@{$self->vertices} = move_points_3D([ @shift ], @{$self->vertices}); $_->mesh->translate(@shift) for @{$self->volumes};
$self->_bounding_box->translate(@shift) if defined $self->_bounding_box; $self->_bounding_box->translate(@shift) if defined $self->_bounding_box;
} }
@ -418,13 +406,8 @@ sub scale {
my ($factor) = @_; my ($factor) = @_;
return if $factor == 1; return if $factor == 1;
# transform vertex coordinates $_->mesh->scale($factor) for @{$self->volumes};
foreach my $vertex (@{$self->vertices}) {
$vertex->[$_] *= $factor for X,Y,Z;
}
$self->_bounding_box->scale($factor) if defined $self->_bounding_box; $self->_bounding_box->scale($factor) if defined $self->_bounding_box;
$self->mesh_stats->{volume} *= ($factor**3) if defined $self->mesh_stats;
} }
sub rotate { sub rotate {
@ -432,13 +415,7 @@ sub rotate {
my ($deg) = @_; my ($deg) = @_;
return if $deg == 0; return if $deg == 0;
my $rad = Slic3r::Geometry::deg2rad($deg); $_->mesh->rotate($deg, Slic3r::Point->(0,0)) for @{$self->volumes};
# transform vertex coordinates
foreach my $vertex (@{$self->vertices}) {
@$vertex = (@{ +(Slic3r::Geometry::rotate_points($rad, undef, [ $vertex->[X], $vertex->[Y] ]))[0] }, $vertex->[Z]);
}
$self->_bounding_box(undef); $self->_bounding_box(undef);
} }
@ -499,20 +476,7 @@ use Moo;
has 'object' => (is => 'ro', weak_ref => 1, required => 1); has 'object' => (is => 'ro', weak_ref => 1, required => 1);
has 'material_id' => (is => 'rw'); has 'material_id' => (is => 'rw');
has 'facets' => (is => 'rw', default => sub { [] }); has 'mesh' => (is => 'rw', required => 1);
sub mesh {
my $self = shift;
my $mesh = Slic3r::TriangleMesh->new;
$mesh->ReadFromPerl($self->object->vertices, $self->facets);
return $mesh;
}
sub facets_count {
my $self = shift;
return scalar(@{$self->facets}); # TODO: optimize in XS
}
package Slic3r::Model::Instance; package Slic3r::Model::Instance;
use Moo; use Moo;

View File

@ -24,6 +24,11 @@ sub used_vertices {
return $self->vertices; return $self->vertices;
} }
sub facets_count {
my $self = shift;
return $self->stats->{number_of_facets};
}
sub bounding_box { sub bounding_box {
my $self = shift; my $self = shift;
return Slic3r::Geometry::BoundingBox->new_from_points_3D($self->used_vertices); return Slic3r::Geometry::BoundingBox->new_from_points_3D($self->used_vertices);

View File

@ -50,6 +50,18 @@ TriangleMesh::ReadSTLFile(char* input_file) {
stl_open(&stl, input_file); stl_open(&stl, input_file);
} }
void
TriangleMesh::write_ascii(char* output_file)
{
stl_write_ascii(&this->stl, output_file, "");
}
void
TriangleMesh::write_binary(char* output_file)
{
stl_write_binary(&this->stl, output_file, "");
}
void TriangleMesh::ReadFromPerl(SV* vertices, SV* facets) void TriangleMesh::ReadFromPerl(SV* vertices, SV* facets)
{ {
stl_initialize(&stl); stl_initialize(&stl);

View File

@ -20,6 +20,8 @@ class TriangleMesh
~TriangleMesh(); ~TriangleMesh();
SV* to_SV(); SV* to_SV();
void ReadSTLFile(char* input_file); void ReadSTLFile(char* input_file);
void write_ascii(char* output_file);
void write_binary(char* output_file);
void ReadFromPerl(SV* vertices, SV* facets); void ReadFromPerl(SV* vertices, SV* facets);
void repair(); void repair();
void WriteOBJFile(char* output_file); void WriteOBJFile(char* output_file);

View File

@ -139,8 +139,8 @@ extern void stl_close(stl_file *stl);
extern void stl_stats_out(stl_file *stl, FILE *file, char *input_file); extern void stl_stats_out(stl_file *stl, FILE *file, char *input_file);
extern void stl_print_edges(stl_file *stl, FILE *file); extern void stl_print_edges(stl_file *stl, FILE *file);
extern void stl_print_neighbors(stl_file *stl, char *file); extern void stl_print_neighbors(stl_file *stl, char *file);
extern void stl_write_ascii(stl_file *stl, char *file, char *label); extern void stl_write_ascii(stl_file *stl, const char *file, const char *label);
extern void stl_write_binary(stl_file *stl, char *file, char *label); extern void stl_write_binary(stl_file *stl, const char *file, const char *label);
extern void stl_check_facets_exact(stl_file *stl); extern void stl_check_facets_exact(stl_file *stl);
extern void stl_check_facets_nearby(stl_file *stl, float tolerance); extern void stl_check_facets_nearby(stl_file *stl, float tolerance);
extern void stl_remove_unconnected_facets(stl_file *stl); extern void stl_remove_unconnected_facets(stl_file *stl);

View File

@ -121,7 +121,7 @@ Normals fixed : %5d\n", stl->stats.normals_fixed);
} }
void void
stl_write_ascii(stl_file *stl, char *file, char *label) stl_write_ascii(stl_file *stl, const char *file, const char *label)
{ {
int i; int i;
FILE *fp; FILE *fp;
@ -241,7 +241,7 @@ stl_put_little_float(FILE *fp, float value_in)
void void
stl_write_binary(stl_file *stl, char *file, char *label) stl_write_binary(stl_file *stl, const char *file, const char *label)
{ {
FILE *fp; FILE *fp;
int i; int i;

View File

@ -11,6 +11,8 @@
TriangleMesh* clone() TriangleMesh* clone()
%code{% const char* CLASS = "Slic3r::TriangleMesh"; RETVAL = new TriangleMesh(*THIS); %}; %code{% const char* CLASS = "Slic3r::TriangleMesh"; RETVAL = new TriangleMesh(*THIS); %};
void ReadSTLFile(char* input_file); void ReadSTLFile(char* input_file);
void write_ascii(char* output_file);
void write_binary(char* output_file);
void ReadFromPerl(SV* vertices, SV* facets); void ReadFromPerl(SV* vertices, SV* facets);
void repair(); void repair();
void WriteOBJFile(char* output_file); void WriteOBJFile(char* output_file);