Finalized the Prusa Control project file format import.
This commit is contained in:
parent
f9023c0603
commit
7ffb3590c4
@ -44,16 +44,16 @@ use Wx::Event qw(EVT_IDLE EVT_COMMAND);
|
|||||||
use base 'Wx::App';
|
use base 'Wx::App';
|
||||||
|
|
||||||
use constant FILE_WILDCARDS => {
|
use constant FILE_WILDCARDS => {
|
||||||
known => 'Known files (*.stl, *.obj, *.amf, *.xml, *.prus)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.prus;*.PRUS',
|
known => 'Known files (*.stl, *.obj, *.amf, *.xml, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.prusa;*.PRUSA',
|
||||||
stl => 'STL files (*.stl)|*.stl;*.STL',
|
stl => 'STL files (*.stl)|*.stl;*.STL',
|
||||||
obj => 'OBJ files (*.obj)|*.obj;*.OBJ',
|
obj => 'OBJ files (*.obj)|*.obj;*.OBJ',
|
||||||
amf => 'AMF files (*.amf)|*.amf;*.AMF;*.xml;*.XML',
|
amf => 'AMF files (*.amf)|*.amf;*.AMF;*.xml;*.XML',
|
||||||
prus => 'PRUS files (*.prus)|*.prus;*.PRUS',
|
prusa => 'Prusa Control files (*.prusa)|*.prusa;*.PRUSA',
|
||||||
ini => 'INI files *.ini|*.ini;*.INI',
|
ini => 'INI files *.ini|*.ini;*.INI',
|
||||||
gcode => 'G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC',
|
gcode => 'G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC',
|
||||||
svg => 'SVG files *.svg|*.svg;*.SVG',
|
svg => 'SVG files *.svg|*.svg;*.SVG',
|
||||||
};
|
};
|
||||||
use constant MODEL_WILDCARD => join '|', @{&FILE_WILDCARDS}{qw(known stl obj amf prus)};
|
use constant MODEL_WILDCARD => join '|', @{&FILE_WILDCARDS}{qw(known stl obj amf prusa)};
|
||||||
|
|
||||||
our $datadir;
|
our $datadir;
|
||||||
# If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden.
|
# If set, the "Controller" tab for the control of the printer over serial line and the serial port settings are hidden.
|
||||||
@ -370,7 +370,7 @@ sub open_model {
|
|||||||
|| $Slic3r::GUI::Settings->{recent}{config_directory}
|
|| $Slic3r::GUI::Settings->{recent}{config_directory}
|
||||||
|| '';
|
|| '';
|
||||||
|
|
||||||
my $dialog = Wx::FileDialog->new($window // $self->GetTopWindow, 'Choose one or more files (STL/OBJ/AMF/PRUS):', $dir, "",
|
my $dialog = Wx::FileDialog->new($window // $self->GetTopWindow, 'Choose one or more files (STL/OBJ/AMF/PRUSA):', $dir, "",
|
||||||
MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
|
MODEL_WILDCARD, wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST);
|
||||||
if ($dialog->ShowModal != wxID_OK) {
|
if ($dialog->ShowModal != wxID_OK) {
|
||||||
$dialog->Destroy;
|
$dialog->Destroy;
|
||||||
|
@ -281,7 +281,7 @@ sub _init_shape_options_page {
|
|||||||
sub _load_stl {
|
sub _load_stl {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
my $dialog = Wx::FileDialog->new($self, 'Choose a file to import bed shape from (STL/OBJ/AMF/PRUS):', "", "", &Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
my $dialog = Wx::FileDialog->new($self, 'Choose a file to import bed shape from (STL/OBJ/AMF/PRUSA):', "", "", &Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
if ($dialog->ShowModal != wxID_OK) {
|
if ($dialog->ShowModal != wxID_OK) {
|
||||||
$dialog->Destroy;
|
$dialog->Destroy;
|
||||||
return;
|
return;
|
||||||
|
@ -387,7 +387,7 @@ sub quick_slice {
|
|||||||
my $input_file;
|
my $input_file;
|
||||||
my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} || $Slic3r::GUI::Settings->{recent}{config_directory} || '';
|
my $dir = $Slic3r::GUI::Settings->{recent}{skein_directory} || $Slic3r::GUI::Settings->{recent}{config_directory} || '';
|
||||||
if (!$params{reslice}) {
|
if (!$params{reslice}) {
|
||||||
my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF/PRUS):', $dir, "", &Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
my $dialog = Wx::FileDialog->new($self, 'Choose a file to slice (STL/OBJ/AMF/PRUSA):', $dir, "", &Slic3r::GUI::MODEL_WILDCARD, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||||
if ($dialog->ShowModal != wxID_OK) {
|
if ($dialog->ShowModal != wxID_OK) {
|
||||||
$dialog->Destroy;
|
$dialog->Destroy;
|
||||||
return;
|
return;
|
||||||
|
@ -2113,7 +2113,7 @@ sub OnDropFiles {
|
|||||||
@_ = ();
|
@_ = ();
|
||||||
|
|
||||||
# only accept STL, OBJ and AMF files
|
# only accept STL, OBJ and AMF files
|
||||||
return 0 if grep !/\.(?:stl|obj|amf(?:\.xml)?|prus)$/i, @$filenames;
|
return 0 if grep !/\.(?:stl|obj|amf(?:\.xml)?|prusa)$/i, @$filenames;
|
||||||
|
|
||||||
$self->{window}->load_file($_) for @$filenames;
|
$self->{window}->load_file($_) for @$filenames;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ sub read_from_file {
|
|||||||
my $model = $input_file =~ /\.stl$/i ? Slic3r::Model->load_stl(Slic3r::encode_path($input_file), basename($input_file))
|
my $model = $input_file =~ /\.stl$/i ? Slic3r::Model->load_stl(Slic3r::encode_path($input_file), basename($input_file))
|
||||||
: $input_file =~ /\.obj$/i ? Slic3r::Model->load_obj(Slic3r::encode_path($input_file), basename($input_file))
|
: $input_file =~ /\.obj$/i ? Slic3r::Model->load_obj(Slic3r::encode_path($input_file), basename($input_file))
|
||||||
: $input_file =~ /\.amf(\.xml)?$/i ? Slic3r::Model->load_amf(Slic3r::encode_path($input_file))
|
: $input_file =~ /\.amf(\.xml)?$/i ? Slic3r::Model->load_amf(Slic3r::encode_path($input_file))
|
||||||
: $input_file =~ /\.prus$/i ? Slic3r::Model->load_prus(Slic3r::encode_path($input_file))
|
: $input_file =~ /\.prusa$/i ? Slic3r::Model->load_prus(Slic3r::encode_path($input_file))
|
||||||
: die "Input file must have .stl, .obj or .amf(.xml) extension\n";
|
: die "Input file must have .stl, .obj or .amf(.xml) extension\n";
|
||||||
|
|
||||||
die "The supplied file couldn't be read because it's empty.\n"
|
die "The supplied file couldn't be read because it's empty.\n"
|
||||||
|
@ -111,7 +111,7 @@ _arguments -S \
|
|||||||
'--support-material-extrusion-width[specify extrusion width for support material]:support material extrusion width in mm or % of --layer-height' \
|
'--support-material-extrusion-width[specify extrusion width for support material]:support material extrusion width in mm or % of --layer-height' \
|
||||||
'--bridge-flow-ratio[specify multiplier for extrusion when bridging]:bridge extrusion multiplier' \
|
'--bridge-flow-ratio[specify multiplier for extrusion when bridging]:bridge extrusion multiplier' \
|
||||||
\
|
\
|
||||||
'*:input file:_files -g "*.(#i)(stl|obj|amf|xml|prus)(-.)"'
|
'*:input file:_files -g "*.(#i)(stl|obj|amf|xml|prusa)(-.)"'
|
||||||
|
|
||||||
# Local Variables: ***
|
# Local Variables: ***
|
||||||
# mode:sh ***
|
# mode:sh ***
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include <wx/wfstream.h>
|
#include <wx/wfstream.h>
|
||||||
#include <wx/zipstrm.h>
|
#include <wx/zipstrm.h>
|
||||||
|
|
||||||
|
#include <Eigen/Geometry>
|
||||||
|
|
||||||
#include "../libslic3r.h"
|
#include "../libslic3r.h"
|
||||||
#include "../Model.hpp"
|
#include "../Model.hpp"
|
||||||
|
|
||||||
@ -29,6 +31,8 @@ struct StlHeader
|
|||||||
uint32_t nTriangles;
|
uint32_t nTriangles;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(StlHeader) == 84, "StlHeader size not correct");
|
||||||
|
|
||||||
// Buffered line reader for the wxInputStream.
|
// Buffered line reader for the wxInputStream.
|
||||||
class LineReader
|
class LineReader
|
||||||
{
|
{
|
||||||
@ -89,7 +93,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int next_line_scanf(char *format, ...)
|
int next_line_scanf(const char *format, ...)
|
||||||
{
|
{
|
||||||
const char *line = next_line();
|
const char *line = next_line();
|
||||||
if (line == nullptr)
|
if (line == nullptr)
|
||||||
@ -147,8 +151,13 @@ bool load_prus(const char *path, Model *model)
|
|||||||
char model_name_tag[1024];
|
char model_name_tag[1024];
|
||||||
sprintf(model_name_tag, "<model name=\"%s\">", name_utf8.data());
|
sprintf(model_name_tag, "<model name=\"%s\">", name_utf8.data());
|
||||||
const char *model_xml = strstr(scene_xml_data.data(), model_name_tag);
|
const char *model_xml = strstr(scene_xml_data.data(), model_name_tag);
|
||||||
float trafo[3][4] = { 0 };
|
const char *zero_tag = "<zero>";
|
||||||
bool trafo_set = false;
|
const char *zero_xml = strstr(scene_xml_data.data(), zero_tag);
|
||||||
|
float trafo[3][4] = { 0 };
|
||||||
|
double instance_rotation = 0.;
|
||||||
|
double instance_scaling_factor = 1.f;
|
||||||
|
Pointf instance_offset(0., 0.);
|
||||||
|
bool trafo_set = false;
|
||||||
if (model_xml != nullptr) {
|
if (model_xml != nullptr) {
|
||||||
model_xml += strlen(model_name_tag);
|
model_xml += strlen(model_name_tag);
|
||||||
const char *position_tag = "<position>";
|
const char *position_tag = "<position>";
|
||||||
@ -157,27 +166,37 @@ bool load_prus(const char *path, Model *model)
|
|||||||
const char *rotation_xml = strstr(model_xml, rotation_tag);
|
const char *rotation_xml = strstr(model_xml, rotation_tag);
|
||||||
const char *scale_tag = "<scale>";
|
const char *scale_tag = "<scale>";
|
||||||
const char *scale_xml = strstr(model_xml, scale_tag);
|
const char *scale_xml = strstr(model_xml, scale_tag);
|
||||||
float position[3], rotation[3][3], scale[3][3];
|
float position[3], rotation[3], scale[3], zero[3];
|
||||||
if (position_xml != nullptr && rotation_xml != nullptr && scale_xml != nullptr &&
|
if (position_xml != nullptr && rotation_xml != nullptr && scale_xml != nullptr && zero_xml != nullptr &&
|
||||||
sscanf(position_xml+strlen(position_tag),
|
sscanf(position_xml+strlen(position_tag),
|
||||||
"[%f, %f, %f]", position, position+1, position+2) == 3 &&
|
"[%f, %f, %f]", position, position+1, position+2) == 3 &&
|
||||||
sscanf(rotation_xml+strlen(rotation_tag),
|
sscanf(rotation_xml+strlen(rotation_tag),
|
||||||
"[[%f, %f, %f], [%f, %f, %f], [%f, %f, %f]]",
|
"[%f, %f, %f]", rotation, rotation+1, rotation+2) == 3 &&
|
||||||
rotation[0], rotation[0]+1, rotation[0]+2,
|
sscanf(scale_xml+strlen(scale_tag),
|
||||||
rotation[1], rotation[1]+1, rotation[1]+2,
|
"[%f, %f, %f]", scale, scale+1, scale+2) == 3 &&
|
||||||
rotation[2], rotation[2]+1, rotation[2]+2) == 9 &&
|
sscanf(zero_xml+strlen(zero_tag),
|
||||||
sscanf(scale_xml+strlen(scale_tag),
|
"[%f, %f, %f]", zero, zero+1, zero+2) == 3) {
|
||||||
"[[%f, %f, %f], [%f, %f, %f], [%f, %f, %f]]",
|
if (scale[0] == scale[1] && scale[1] == scale[2]) {
|
||||||
scale[0], scale[0]+1, scale[0]+2,
|
instance_scaling_factor = scale[0];
|
||||||
scale[1], scale[1]+1, scale[1]+2,
|
scale[0] = scale[1] = scale[2] = 1.;
|
||||||
scale[2], scale[2]+1, scale[2]+2) == 9) {
|
|
||||||
for (size_t r = 0; r < 3; ++ r) {
|
|
||||||
for (size_t c = 0; c < 3; ++ c) {
|
|
||||||
for (size_t i = 0; i < 3; ++ i)
|
|
||||||
trafo[r][c] += rotation[r][i]*scale[i][c];
|
|
||||||
}
|
|
||||||
trafo[r][3] = position[r];
|
|
||||||
}
|
}
|
||||||
|
if (rotation[0] == 0. && rotation[1] == 0.) {
|
||||||
|
instance_rotation = - rotation[2];
|
||||||
|
rotation[2] = 0.;
|
||||||
|
}
|
||||||
|
Eigen::Matrix3f mat_rot, mat_scale, mat_trafo;
|
||||||
|
mat_rot = Eigen::AngleAxisf(-rotation[2], Eigen::Vector3f::UnitZ()) *
|
||||||
|
Eigen::AngleAxisf(-rotation[1], Eigen::Vector3f::UnitY()) *
|
||||||
|
Eigen::AngleAxisf(-rotation[0], Eigen::Vector3f::UnitX());
|
||||||
|
mat_scale = Eigen::Scaling(scale[0], scale[1], scale[2]);
|
||||||
|
mat_trafo = mat_rot * mat_scale;
|
||||||
|
for (size_t r = 0; r < 3; ++ r) {
|
||||||
|
for (size_t c = 0; c < 3; ++ c)
|
||||||
|
trafo[r][c] += mat_trafo(r, c);
|
||||||
|
}
|
||||||
|
instance_offset.x = position[0] - zero[0];
|
||||||
|
instance_offset.y = position[1] - zero[1];
|
||||||
|
trafo[2][3] = position[2] / instance_scaling_factor;
|
||||||
trafo_set = true;
|
trafo_set = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,15 +216,27 @@ bool load_prus(const char *path, Model *model)
|
|||||||
stl.stats.number_of_facets = header.nTriangles;
|
stl.stats.number_of_facets = header.nTriangles;
|
||||||
stl.stats.original_num_facets = header.nTriangles;
|
stl.stats.original_num_facets = header.nTriangles;
|
||||||
stl_allocate(&stl);
|
stl_allocate(&stl);
|
||||||
if (zip.ReadAll((void*)stl.facet_start, 50 * header.nTriangles)) {
|
if (header.nTriangles > 0 && zip.ReadAll((void*)stl.facet_start, 50 * header.nTriangles)) {
|
||||||
|
if (sizeof(stl_facet) > SIZEOF_STL_FACET) {
|
||||||
|
// The stl.facet_start is not packed tightly. Unpack the array of stl_facets.
|
||||||
|
unsigned char *data = (unsigned char*)stl.facet_start;
|
||||||
|
for (size_t i = header.nTriangles - 1; i > 0; -- i)
|
||||||
|
memmove(data + i * sizeof(stl_facet), data + i * SIZEOF_STL_FACET, SIZEOF_STL_FACET);
|
||||||
|
}
|
||||||
// All the faces have been read.
|
// All the faces have been read.
|
||||||
stl_get_size(&stl);
|
stl_get_size(&stl);
|
||||||
mesh.repair();
|
mesh.repair();
|
||||||
// Transform the model.
|
// Transform the model.
|
||||||
stl_transform(&stl, &trafo[0][0]);
|
stl_transform(&stl, &trafo[0][0]);
|
||||||
|
if (std::abs(stl.stats.min.z) < EPSILON)
|
||||||
|
stl.stats.min.z = 0.;
|
||||||
// Add a mesh to a model.
|
// Add a mesh to a model.
|
||||||
if (mesh.facets_count() > 0) {
|
if (mesh.facets_count() > 0) {
|
||||||
model->add_object(name_utf8.data(), path, std::move(mesh));
|
ModelObject *object = model->add_object(name_utf8.data(), path, std::move(mesh));
|
||||||
|
ModelInstance *instance = object->add_instance();
|
||||||
|
instance->rotation = instance_rotation;
|
||||||
|
instance->scaling_factor = instance_scaling_factor;
|
||||||
|
instance->offset = instance_offset;
|
||||||
++ num_models;
|
++ num_models;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user