Incomplete work to store TriangleMesh objects in Model objects instead of extracting vertices and facets
This commit is contained in:
parent
78ee6e5d6d
commit
11e18f681d
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user