Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--slic3r.sublime-project2
-rw-r--r--xs/CMakeLists.txt13
-rw-r--r--xs/src/libslic3r/GCode.cpp53
-rw-r--r--xs/src/libslic3r/GCode.hpp4
-rw-r--r--xs/src/libslic3r/GCode/ToolOrdering.cpp58
-rw-r--r--xs/src/libslic3r/GCode/ToolOrdering.hpp22
-rw-r--r--xs/src/libslic3r/GCode/WipeTower.hpp18
-rw-r--r--xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp168
-rw-r--r--xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp7
-rw-r--r--xs/src/libslic3r/Print.cpp21
-rw-r--r--xs/src/libslic3r/Print.hpp31
-rw-r--r--xs/src/slic3r/GUI/3DScene.cpp21
-rw-r--r--xs/src/xsinit.h1
13 files changed, 325 insertions, 94 deletions
diff --git a/slic3r.sublime-project b/slic3r.sublime-project
index 096a4859b..3f2fc36dc 100644
--- a/slic3r.sublime-project
+++ b/slic3r.sublime-project
@@ -26,7 +26,7 @@
"file_regex": "^(..[^:]*)\\(([0-9]+)\\)(.*)$",
// For GCC:
// "file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
- "shell_cmd": "chdir & ninja -j 6",
+ "shell_cmd": "chdir & ninja -j 6 -v",
"env": {
// "PATH": "C:\\Program Files (x86)\\MSBuild\\12.0\\bin\\amd64;C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\BIN\\amd64;C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\Common7\\IDE;C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\Common7\\Tools;%PATH%;c:\\wperl64d\\site\\bin;c:\\wperl64d\\bin",
// "PERL_CPANM_HOME": "c:\\wperl64d\\cpanm",
diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt
index 9d7c31100..617f79055 100644
--- a/xs/CMakeLists.txt
+++ b/xs/CMakeLists.txt
@@ -394,8 +394,15 @@ target_compile_options(XS PRIVATE ${PerlEmbed_CCFLAGS})
# If the Perl is compiled with optimization off, disable optimization over the whole project.
if (WIN32 AND ";${PerlEmbed_CCFLAGS};" MATCHES ";[-/]Od;")
message(STATUS "Perl compiled without optimization. Disabling optimization for the Slic3r build.")
- set(CMAKE_CXX_FLAGS_RELEASE /Od /Zi)
- set(CMAKE_C_FLAGS_RELEASE /Od /Zi)
+ message("Old CMAKE_CXX_FLAGS_RELEASE: ${CMAKE_CXX_FLAGS_RELEASE}")
+ message("Old CMAKE_CXX_FLAGS_RELWITHDEBINFO: ${CMAKE_CXX_FLAGS_RELEASE}")
+ message("Old CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS_RELEASE}")
+ set(CMAKE_CXX_FLAGS_RELEASE "/MD /Od /Zi /EHsc /DNDEBUG")
+ set(CMAKE_C_FLAGS_RELEASE "/MD /Od /Zi /DNDEBUG")
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /EHsc /DNDEBUG")
+ set(CMAKE_C_FLAGS_RELWITHDEBINFO "/MD /Od /Zi /DNDEBUG")
+ set(CMAKE_CXX_FLAGS "/MD /Od /Zi /EHsc /DNDEBUG")
+ set(CMAKE_C_FLAGS "/MD /Od /Zi /DNDEBUG")
endif()
# The following line will add -fPIC on Linux to make the XS.so rellocable.
add_definitions(${PerlEmbed_CCCDLFLAGS})
@@ -437,6 +444,8 @@ if(MSVC)
# Suppress implicit linking of the TBB libraries by the Visual Studio compiler.
add_definitions(-D__TBB_NO_IMPLICIT_LINKAGE)
endif()
+# The Intel TBB library will use the std::exception_ptr feature of C++11.
+add_definitions(-DTBB_USE_CAPTURED_EXCEPTION=0)
target_link_libraries(XS ${TBB_LIBRARIES})
# Find and configure wxWidgets
diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp
index 699621974..3c7df750e 100644
--- a/xs/src/libslic3r/GCode.cpp
+++ b/xs/src/libslic3r/GCode.cpp
@@ -192,6 +192,33 @@ std::string WipeTowerIntegration::append_tcr(GCode &gcodegen, const WipeTower::T
return gcode;
}
+std::string WipeTowerIntegration::prime(GCode &gcodegen)
+{
+ assert(m_layer_idx == 0);
+ std::string gcode;
+
+ if (&m_priming != nullptr && ! m_priming.extrusions.empty()) {
+ // Let the tool change be executed by the wipe tower class.
+ // Inform the G-code writer about the changes done behind its back.
+ gcode += m_priming.gcode;
+ // Let the m_writer know the current extruder_id, but ignore the generated G-code.
+ gcodegen.writer().toolchange(m_priming.extrusions.back().tool);
+ // A phony move to the end position at the wipe tower.
+ gcodegen.writer().travel_to_xy(Pointf(m_priming.end_pos.x, m_priming.end_pos.y));
+ gcodegen.set_last_pos(wipe_tower_point_to_object_point(gcodegen, m_priming.end_pos));
+
+ // Prepare a future wipe.
+ gcodegen.m_wipe.path.points.clear();
+ // Start the wipe at the current position.
+ gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen, m_priming.end_pos));
+ // Wipe end point: Wipe direction away from the closer tower edge to the further tower edge.
+ gcodegen.m_wipe.path.points.emplace_back(wipe_tower_point_to_object_point(gcodegen,
+ WipeTower::xy((std::abs(m_left - m_priming.end_pos.x) < std::abs(m_right - m_priming.end_pos.x)) ? m_right : m_left,
+ m_priming.end_pos.y)));
+ }
+ return gcode;
+}
+
std::string WipeTowerIntegration::tool_change(GCode &gcodegen, int extruder_id, bool finish_layer)
{
std::string gcode;
@@ -522,7 +549,7 @@ bool GCode::_do_export(Print &print, FILE *file)
writeln(file, m_placeholder_parser.process(print.config.start_gcode.value, initial_extruder_id));
// Process filament-specific gcode in extruder order.
for (const std::string &start_gcode : print.config.start_filament_gcode.values)
- writeln(file, m_placeholder_parser.process(start_gcode, &start_gcode - &print.config.start_filament_gcode.values.front()));
+ writeln(file, m_placeholder_parser.process(start_gcode, (unsigned int)(&start_gcode - &print.config.start_filament_gcode.values.front())));
this->_print_first_layer_extruder_temperatures(file, print, initial_extruder_id, true);
// Set other general things.
@@ -647,8 +674,10 @@ bool GCode::_do_export(Print &print, FILE *file)
std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print = collect_layers_to_print(print);
// Prusa Multi-Material wipe tower.
if (print.has_wipe_tower() &&
- ! tool_ordering.empty() && tool_ordering.front().wipe_tower_partitions > 0)
- m_wipe_tower.reset(new WipeTowerIntegration(print.config, print.m_wipe_tower_tool_changes, *print.m_wipe_tower_final_purge.get()));
+ ! tool_ordering.empty() && tool_ordering.front().wipe_tower_partitions > 0) {
+ m_wipe_tower.reset(new WipeTowerIntegration(print.config, *print.m_wipe_tower_priming.get(), print.m_wipe_tower_tool_changes, *print.m_wipe_tower_final_purge.get()));
+ write(file, m_wipe_tower->prime(*this));
+ }
// Extrude the layers.
for (auto &layer : layers_to_print) {
const ToolOrdering::LayerTools &layer_tools = tool_ordering.tools_for_layer(layer.first);
@@ -668,7 +697,7 @@ bool GCode::_do_export(Print &print, FILE *file)
write(file, m_writer.set_fan(false));
// Process filament-specific gcode in extruder order.
for (const std::string &end_gcode : print.config.end_filament_gcode.values)
- writeln(file, m_placeholder_parser.process(end_gcode, &end_gcode - &print.config.end_filament_gcode.values.front()));
+ writeln(file, m_placeholder_parser.process(end_gcode, (unsigned int)(&end_gcode - &print.config.end_filament_gcode.values.front())));
writeln(file, m_placeholder_parser.process(print.config.end_gcode, m_writer.extruder()->id()));
write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100%
write(file, m_writer.postamble());
@@ -1471,7 +1500,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
} else if (seam_position == spNearest || seam_position == spAligned || seam_position == spRear) {
Polygon polygon = loop.polygon();
const coordf_t nozzle_dmr = EXTRUDER_CONFIG(nozzle_diameter);
- const coord_t nozzle_r = scale_(0.5*nozzle_dmr);
+ const coord_t nozzle_r = coord_t(scale_(0.5 * nozzle_dmr) + 0.5);
// Retrieve the last start position for this object.
float last_pos_weight = 1.f;
@@ -1524,11 +1553,11 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
penalty = penaltyConvexVertex;
else if (ccwAngle < 0.f) {
// Interpolate penalty between maximum and zero.
- penalty = penaltyFlatSurface * bspline_kernel(ccwAngle * (PI * 2. / 3.));
+ penalty = penaltyFlatSurface * bspline_kernel(ccwAngle * float(PI * 2. / 3.));
} else {
assert(ccwAngle >= 0.f);
// Interpolate penalty between maximum and the penalty for a convex vertex.
- penalty = penaltyConvexVertex + (penaltyFlatSurface - penaltyConvexVertex) * bspline_kernel(ccwAngle * (PI * 2. / 3.));
+ penalty = penaltyConvexVertex + (penaltyFlatSurface - penaltyConvexVertex) * bspline_kernel(ccwAngle * float(PI * 2. / 3.));
}
// Give a negative penalty for points close to the last point or the prefered seam location.
//float dist_to_last_pos_proj = last_pos_proj.distance_to(polygon.points[i]);
@@ -1543,8 +1572,8 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// Penalty for overhangs.
if (lower_layer_edge_grid && (*lower_layer_edge_grid)) {
// Use the edge grid distance field structure over the lower layer to calculate overhangs.
- coord_t nozzle_r = scale_(0.5*nozzle_dmr);
- coord_t search_r = scale_(0.8*nozzle_dmr);
+ coord_t nozzle_r = coord_t(floor(scale_(0.5 * nozzle_dmr) + 0.5));
+ coord_t search_r = coord_t(floor(scale_(0.8 * nozzle_dmr) + 0.5));
for (size_t i = 0; i < polygon.points.size(); ++ i) {
const Point &p = polygon.points[i];
coordf_t dist;
@@ -1555,7 +1584,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
// If the approximate Signed Distance Field was initialized over lower_layer_edge_grid,
// then the signed distnace shall always be known.
assert(found);
- penalties[i] += extrudate_overlap_penalty(nozzle_r, penaltyOverhangHalf, dist);
+ penalties[i] += extrudate_overlap_penalty(float(nozzle_r), penaltyOverhangHalf, float(dist));
}
}
@@ -1651,7 +1680,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
}
// reset acceleration
- gcode += m_writer.set_acceleration(m_config.default_acceleration.value);
+ gcode += m_writer.set_acceleration((unsigned int)(m_config.default_acceleration.value + 0.5));
if (m_wipe.enable)
m_wipe.path = paths.front().polyline; // TODO: don't limit wipe to last path
@@ -1708,7 +1737,7 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string
m_wipe.path.reverse();
}
// reset acceleration
- gcode += m_writer.set_acceleration(m_config.default_acceleration.value);
+ gcode += m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
return gcode;
}
diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp
index ac0af3f2c..da97fd23a 100644
--- a/xs/src/libslic3r/GCode.hpp
+++ b/xs/src/libslic3r/GCode.hpp
@@ -77,16 +77,19 @@ class WipeTowerIntegration {
public:
WipeTowerIntegration(
const PrintConfig &print_config,
+ const WipeTower::ToolChangeResult &priming,
const std::vector<std::vector<WipeTower::ToolChangeResult>> &tool_changes,
const WipeTower::ToolChangeResult &final_purge) :
m_left(float(print_config.wipe_tower_x.value)),
m_right(float(print_config.wipe_tower_x.value + print_config.wipe_tower_width.value)),
+ m_priming(priming),
m_tool_changes(tool_changes),
m_final_purge(final_purge),
m_layer_idx(-1),
m_tool_change_idx(0),
m_brim_done(false) {}
+ std::string prime(GCode &gcodegen);
void next_layer() { ++ m_layer_idx; m_tool_change_idx = 0; }
std::string tool_change(GCode &gcodegen, int extruder_id, bool finish_layer);
std::string finalize(GCode &gcodegen);
@@ -99,6 +102,7 @@ private:
const float m_left;
const float m_right;
// Reference to cached values at the Printer class.
+ const WipeTower::ToolChangeResult &m_priming;
const std::vector<std::vector<WipeTower::ToolChangeResult>> &m_tool_changes;
const WipeTower::ToolChangeResult &m_final_purge;
// Current layer index.
diff --git a/xs/src/libslic3r/GCode/ToolOrdering.cpp b/xs/src/libslic3r/GCode/ToolOrdering.cpp
index 2bf659bb2..703e4262e 100644
--- a/xs/src/libslic3r/GCode/ToolOrdering.cpp
+++ b/xs/src/libslic3r/GCode/ToolOrdering.cpp
@@ -8,7 +8,7 @@ namespace Slic3r {
// For the use case when each object is printed separately
// (print.config.complete_objects is true).
-ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder)
+ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder, bool prime_multi_material)
{
if (object.layers.empty())
return;
@@ -31,13 +31,15 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude
this->reorder_extruders(first_extruder);
this->fill_wipe_tower_partitions(object.print()->config, object.layers.front()->print_z - object.layers.front()->height);
+
+ this->collect_extruder_statistics(prime_multi_material);
}
// For the use case when all objects are printed at once.
// (print.config.complete_objects is false).
-ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder)
+ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material)
{
- // Initialize the print layers for all objects and all layers.
+ // Initialize the print layers for all objects and all layers.
coordf_t object_bottom_z = 0.;
{
std::vector<coordf_t> zs;
@@ -61,22 +63,8 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder)
this->reorder_extruders(first_extruder);
this->fill_wipe_tower_partitions(print.config, object_bottom_z);
-}
-
-unsigned int ToolOrdering::first_extruder() const
-{
- for (const auto &lt : m_layer_tools)
- if (! lt.extruders.empty())
- return lt.extruders.front();
- return (unsigned int)-1;
-}
-unsigned int ToolOrdering::last_extruder() const
-{
- for (auto lt_it = m_layer_tools.rbegin(); lt_it != m_layer_tools.rend(); ++ lt_it)
- if (! lt_it->extruders.empty())
- return lt_it->extruders.back();
- return (unsigned int)-1;
+ this->collect_extruder_statistics(prime_multi_material);
}
ToolOrdering::LayerTools& ToolOrdering::tools_for_layer(coordf_t print_z)
@@ -289,4 +277,38 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
}
}
+void ToolOrdering::collect_extruder_statistics(bool prime_multi_material)
+{
+ m_first_printing_extruder = (unsigned int)-1;
+ for (const auto &lt : m_layer_tools)
+ if (! lt.extruders.empty()) {
+ m_first_printing_extruder = lt.extruders.front();
+ break;
+ }
+
+ m_last_printing_extruder = (unsigned int)-1;
+ for (auto lt_it = m_layer_tools.rbegin(); lt_it != m_layer_tools.rend(); ++ lt_it)
+ if (! lt_it->extruders.empty()) {
+ m_last_printing_extruder = lt_it->extruders.back();
+ break;
+ }
+
+ m_all_printing_extruders.clear();
+ for (const auto &lt : m_layer_tools) {
+ append(m_all_printing_extruders, lt.extruders);
+ sort_remove_duplicates(m_all_printing_extruders);
+ }
+
+ if (prime_multi_material && ! m_all_printing_extruders.empty()) {
+ // Reorder m_all_printing_extruders in the sequence they will be primed, the last one will be m_first_printing_extruder.
+ // Then set m_first_printing_extruder to the 1st extruder primed.
+ m_all_printing_extruders.erase(
+ std::remove_if(m_all_printing_extruders.begin(), m_all_printing_extruders.end(),
+ [ this ](const unsigned int eid) { return eid == m_first_printing_extruder; }),
+ m_all_printing_extruders.end());
+ m_all_printing_extruders.emplace_back(m_first_printing_extruder);
+ m_first_printing_extruder = m_all_printing_extruders.front();
+ }
+}
+
} // namespace Slic3r
diff --git a/xs/src/libslic3r/GCode/ToolOrdering.hpp b/xs/src/libslic3r/GCode/ToolOrdering.hpp
index 77de726ba..ecf2d522f 100644
--- a/xs/src/libslic3r/GCode/ToolOrdering.hpp
+++ b/xs/src/libslic3r/GCode/ToolOrdering.hpp
@@ -45,19 +45,22 @@ public:
// For the use case when each object is printed separately
// (print.config.complete_objects is true).
- ToolOrdering(const PrintObject &object, unsigned int first_extruder = (unsigned int)-1);
+ ToolOrdering(const PrintObject &object, unsigned int first_extruder = (unsigned int)-1, bool prime_multi_material = false);
// For the use case when all objects are printed at once.
// (print.config.complete_objects is false).
- ToolOrdering(const Print &print, unsigned int first_extruder = (unsigned int)-1);
+ ToolOrdering(const Print &print, unsigned int first_extruder = (unsigned int)-1, bool prime_multi_material = false);
void clear() { m_layer_tools.clear(); }
// Get the first extruder printing the layer_tools, returns -1 if there is no layer printed.
- unsigned int first_extruder() const;
+ unsigned int first_extruder() const { return m_first_printing_extruder; }
// Get the first extruder printing the layer_tools, returns -1 if there is no layer printed.
- unsigned int last_extruder() const;
+ unsigned int last_extruder() const { return m_last_printing_extruder; }
+
+ // For a multi-material print, the printing extruders are ordered in the order they shall be primed.
+ std::vector<unsigned int> all_extruders() const { return m_all_printing_extruders; }
// Find LayerTools with the closest print_z.
LayerTools& tools_for_layer(coordf_t print_z);
@@ -74,8 +77,15 @@ private:
void collect_extruders(const PrintObject &object);
void reorder_extruders(unsigned int last_extruder_id);
void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z);
-
- std::vector<LayerTools> m_layer_tools;
+ void collect_extruder_statistics(bool prime_multi_material);
+
+ std::vector<LayerTools> m_layer_tools;
+ // First printing extruder, including the multi-material priming sequence.
+ unsigned int m_first_printing_extruder;
+ // Final printing extruder.
+ unsigned int m_last_printing_extruder;
+ // All extruders, which extrude some material over m_layer_tools.
+ std::vector<unsigned int> m_all_printing_extruders;
};
} // namespace SLic3r
diff --git a/xs/src/libslic3r/GCode/WipeTower.hpp b/xs/src/libslic3r/GCode/WipeTower.hpp
index db3977246..cccbe23d8 100644
--- a/xs/src/libslic3r/GCode/WipeTower.hpp
+++ b/xs/src/libslic3r/GCode/WipeTower.hpp
@@ -89,11 +89,27 @@ public:
// Time elapsed over this tool change.
// This is useful not only for the print time estimation, but also for the control of layer cooling.
float elapsed_time;
+
+ // Sum the total length of the extrusion.
+ float total_extrusion_length_in_plane() {
+ float e_length = 0.f;
+ for (size_t i = 1; i < this->extrusions.size(); ++ i) {
+ const Extrusion &e = this->extrusions[i];
+ if (e.width > 0) {
+ xy v = e.pos - (&e - 1)->pos;
+ e_length += sqrt(v.x*v.x+v.y*v.y);
+ }
+ }
+ return e_length;
+ }
};
+ // Returns gcode to prime the nozzles at the front edge of the print bed.
+ virtual ToolChangeResult prime(float first_layer_height, std::vector<unsigned int> tools, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0;
+
// Returns gcode for toolchange and the end position.
// if new_tool == -1, just unload the current filament over the wipe tower.
- virtual ToolChangeResult tool_change(int new_tool, bool last_in_layer, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0;
+ virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0;
// Close the current wipe tower layer with a perimeter and possibly fill the unfilled space with a zig-zag.
// Call this method only if layer_finished() is false.
diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
index ec01e09dc..4e2921efd 100644
--- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
+++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.cpp
@@ -315,6 +315,29 @@ private:
Writer& operator=(const Writer &rhs);
};
+/*
+class Material
+{
+public:
+ std::string name;
+ std::string type;
+
+ struct RammingStep {
+// float length;
+ float extrusion_multiplier; // sirka linky
+ float extrusion;
+ float speed;
+ };
+ std::vector<RammingStep> ramming_sequence;
+
+ // Number and speed of the cooling moves.
+ std::vector<float> cooling_moves;
+
+ // Percentage of the speed overide, in pairs of <z, percentage>
+ std::vector<std::pair<float, int>> speed_override;
+};
+*/
+
} // namespace PrusaMultiMaterial
WipeTowerPrusaMM::material_type WipeTowerPrusaMM::parse_material(const char *name)
@@ -340,7 +363,92 @@ WipeTowerPrusaMM::material_type WipeTowerPrusaMM::parse_material(const char *nam
return INVALID;
}
-WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(int tool, bool last_in_layer, Purpose purpose)
+// Returns gcode to prime the nozzles at the front edge of the print bed.
+WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(float first_layer_height, std::vector<unsigned int> tools, Purpose purpose)
+{
+ this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false);
+
+ float wipe_area = m_wipe_area;
+ // Calculate the amount of wipe over the wipe tower brim following the prime, decrease wipe_area
+ // with the amount of material extruded over the brim.
+ {
+ // Simulate the brim extrusions, summ the length of the extrusion.
+ float e_length = this->tool_change(0, false, PURPOSE_EXTRUDE).total_extrusion_length_in_plane();
+ // Shrink wipe_area by the amount of extrusion extruded by the finish_layer().
+ // Y stepping of the wipe extrusions.
+ float dy = m_perimeter_width * 0.8f;
+ // Number of whole wipe lines, that would be extruded to wipe as much material as the finish_layer().
+ // Minimum wipe area is 5mm wide.
+ //FIXME calculate the purge_lines_width precisely.
+ float purge_lines_width = 1.3f;
+ wipe_area = std::max(5.f, m_wipe_area - floor(e_length / m_wipe_tower_width) * dy - purge_lines_width);
+ }
+
+ this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false);
+ this->m_num_layer_changes = 0;
+ this->m_current_tool = tools.front();
+
+ box_coordinates cleaning_box(xy(0.f, - 4.0f), m_wipe_tower_width, wipe_area);
+
+ PrusaMultiMaterial::Writer writer;
+ writer.set_extrusion_flow(m_extrusion_flow)
+ .set_z(m_z_pos)
+ .set_layer_height(m_layer_height)
+ .set_initial_tool(m_current_tool)
+ .append(";--------------------\n"
+ "; CP PRIMING START\n")
+ .append(";--------------------\n")
+ .speed_override(100);
+
+ // Always move to the starting position.
+ writer.travel(cleaning_box.ld, 7200);
+ // Increase the extruder driver current to allow fast ramming.
+ writer.set_extruder_trimpot(750);
+
+ if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) {
+ for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) {
+ unsigned int tool = tools[idx_tool];
+ // Select the tool, set a speed override for soluble and flex materials.
+ toolchange_Change(writer, tool, m_material[tool]);
+ // Prime the tool.
+ toolchange_Load(writer, cleaning_box);
+ if (idx_tool + 1 == tools.size()) {
+ // Last tool should not be unloaded, but it should be wiped enough to become of a pure color.
+ toolchange_Wipe(writer, cleaning_box);
+ } else {
+ // Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool.
+ toolchange_Unload(writer, cleaning_box, m_material[m_current_tool], m_first_layer_temperature[tool]);
+ cleaning_box.translate(m_wipe_tower_width, 0.f);
+ writer.travel(cleaning_box.ld, 7200);
+ }
+ ++ m_num_tool_changes;
+ }
+ }
+
+ // Reset the extruder current to a normal value.
+ writer.set_extruder_trimpot(550)
+ .feedrate(6000)
+ .flush_planner_queue()
+ .reset_extruder()
+ .append("; CP PRIMING END\n"
+ ";------------------\n"
+ "\n\n");
+
+ // Force m_idx_tool_change_in_layer to -1, so that tool_change() will know to extrude the wipe tower brim.
+ m_idx_tool_change_in_layer = (unsigned int)(-1);
+
+ ToolChangeResult result;
+ result.print_z = this->m_z_pos;
+ result.layer_height = this->m_layer_height;
+ result.gcode = writer.gcode();
+ result.elapsed_time = writer.elapsed_time();
+ result.extrusions = writer.extrusions();
+ result.start_pos = writer.start_pos();
+ result.end_pos = writer.pos();
+ return result;
+}
+
+WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, bool last_in_layer, Purpose purpose)
{
// Either it is the last tool unload,
// or there must be a nonzero wipe tower partitions available.
@@ -363,14 +471,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(int tool, bool last_in
unsigned int old_idx_tool_change = m_idx_tool_change_in_layer;
float old_wipe_start_y = m_current_wipe_start_y;
m_current_wipe_start_y += wipe_area;
- ToolChangeResult tcr = this->finish_layer(PURPOSE_EXTRUDE);
- for (size_t i = 1; i < tcr.extrusions.size(); ++ i) {
- const Extrusion &e = tcr.extrusions[i];
- if (e.width > 0) {
- xy v = e.pos - (&e - 1)->pos;
- e_length += sqrt(v.x*v.x+v.y*v.y);
- }
- }
+ e_length = this->finish_layer(PURPOSE_EXTRUDE).total_extrusion_length_in_plane();
m_idx_tool_change_in_layer = old_idx_tool_change;
m_current_wipe_start_y = old_wipe_start_y;
}
@@ -431,10 +532,10 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(int tool, bool last_in
// Increase the extruder driver current to allow fast ramming.
writer.set_extruder_trimpot(750);
// Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool.
- toolchange_Unload(writer, cleaning_box, m_material[m_current_tool],
- m_is_first_layer ? m_first_layer_temperature[tool] : m_temperature[tool]);
- if (tool >= 0) {
+ if (tool != (unsigned int)-1) {
+ toolchange_Unload(writer, cleaning_box, m_material[m_current_tool],
+ m_is_first_layer ? m_first_layer_temperature[tool] : m_temperature[tool]);
// This is not the last change.
// Change the tool, set a speed override for soluble and flex materials.
toolchange_Change(writer, tool, m_material[tool]);
@@ -455,7 +556,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(int tool, bool last_in
if (purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE)
writer.travel(box.ru, 7200)
.travel(box.lu);
- }
+ } else
+ toolchange_Unload(writer, cleaning_box, m_material[m_current_tool], m_temperature[m_current_tool]);
// Reset the extruder current to a normal value.
writer.set_extruder_trimpot(550)
@@ -587,24 +689,27 @@ void WipeTowerPrusaMM::toolchange_Unload(
{
case ABS:
// ramming start end y increment amount feedrate
- writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 0.2f, 0, 1.2f * e, 4000)
- .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.2f, e0, 1.6f * e, 4600)
- .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 1.2f, e0, 1.8f * e, 5000)
- .ram(xr - m_perimeter_width * 2, xl + m_perimeter_width * 2, y_step * 1.2f, e0, 1.8f * e, 5000);
+ writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 0.2f, 0, 1.2f * e, 4000)
+ .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.2f, e0, 1.6f * e, 4600)
+ .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 1.2f, e0, 1.8f * e, 5000)
+ .ram(xr - m_perimeter_width * 2, xl + m_perimeter_width * 2, y_step * 1.2f, e0, 1.8f * e, 5000);
break;
case PVA:
- writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 0.2f, 0, 3, 4000)
- .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.5f, 0, 3, 4500)
- .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 1.5f, 0, 3, 4800)
- .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.5f, 0, 3, 5000);
+ // Used for the PrimaSelect PVA
+ writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 0.2f, 0, 1.75f * e, 4000)
+ .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.5f, 0, 1.75f * e, 4500)
+ .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 1.5f, 0, 1.75f * e, 4800)
+ .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.5f, 0, 1.75f * e, 5000);
break;
case SCAFF:
- writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 2.f, 0, 3, 4000)
- .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 3.f, 0, 4, 4600)
- .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 3.f, 0, 4.5, 5200);
+ writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 2.f, 0, 1.75f * e, 4000)
+ .ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 3.f, 0, 2.34f * e, 4600)
+ .ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 3.f, 0, 2.63f * e, 5200);
break;
default:
- writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 0.2f, 0, 1.6f * e, 4000)
+ // PLA, PLA/PHA and others
+ // Used for the Verbatim BVOH, PET, NGEN, co-polyesters
+ writer.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width, y_step * 0.2f, 0, 1.60f * e, 4000)
.ram(xr - m_perimeter_width, xl + m_perimeter_width, y_step * 1.2f, e0, 1.65f * e, 4600)
.ram(xl + m_perimeter_width * 2, xr - m_perimeter_width * 2, y_step * 1.2f, e0, 1.74f * e, 5200);
}
@@ -624,12 +729,6 @@ void WipeTowerPrusaMM::toolchange_Unload(
.suppress_preview();
switch (current_material)
{
- case ABS:
- writer.cool(xl, xr, 3, -5, 1600)
- .cool(xl, xr, 5, -5, 2000)
- .cool(xl, xr, 5, -5, 2400)
- .cool(xl, xr, 5, -3, 2400);
- break;
case PVA:
writer.cool(xl, xr, 3, -5, 1600)
.cool(xl, xr, 5, -5, 2000)
@@ -659,8 +758,8 @@ void WipeTowerPrusaMM::toolchange_Unload(
// Change the tool, set a speed override for solube and flex materials.
void WipeTowerPrusaMM::toolchange_Change(
PrusaMultiMaterial::Writer &writer,
- const int new_tool,
- material_type new_material)
+ const unsigned int new_tool,
+ material_type new_material)
{
// Speed override for the material. Go slow for flex and soluble materials.
int speed_override;
@@ -687,8 +786,11 @@ void WipeTowerPrusaMM::toolchange_Load(
// Load the filament while moving left / right,
// so the excess material will not create a blob at a single position.
.suppress_preview()
+ // Accelerate the filament loading
.load_move_x(xr, 20, 1400)
+ // Fast loading phase
.load_move_x(xl, 40, 3000)
+ // Slowing down
.load_move_x(xr, 20, 1600)
.load_move_x(xl, 10, 1000)
.resume_preview();
diff --git a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp
index baf01f427..c21c62486 100644
--- a/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp
+++ b/xs/src/libslic3r/GCode/WipeTowerPrusaMM.hpp
@@ -107,9 +107,12 @@ public:
// The wipe tower is finished, there should be no more tool changes or wipe tower prints.
virtual bool finished() const { return m_max_color_changes == 0; }
+ // Returns gcode to prime the nozzles at the front edge of the print bed.
+ virtual ToolChangeResult prime(float first_layer_height, std::vector<unsigned int> tools, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE);
+
// Returns gcode for a toolchange and a final print head position.
// On the first layer, extrude a brim around the future wipe tower first.
- virtual ToolChangeResult tool_change(int new_tool, bool last_in_layer, Purpose purpose);
+ virtual ToolChangeResult tool_change(unsigned int new_tool, bool last_in_layer, Purpose purpose);
// Close the current wipe tower layer with a perimeter and possibly fill the unfilled space with a zig-zag.
// Call this method only if layer_finished() is false.
@@ -218,7 +221,7 @@ private:
void toolchange_Change(
PrusaMultiMaterial::Writer &writer,
- int new_tool,
+ const unsigned int new_tool,
material_type new_material);
void toolchange_Load(
diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp
index 6ae36ec58..2069a7e55 100644
--- a/xs/src/libslic3r/Print.cpp
+++ b/xs/src/libslic3r/Print.cpp
@@ -54,6 +54,10 @@ void Print::reload_object(size_t /* idx */)
this->add_model_object(mo);
}
+// Reloads the model instances into the print class.
+// The slicing shall not be running as the modified model instances at the print
+// are used for the brim & skirt calculation.
+// Returns true if the brim or skirt have been invalidated.
bool Print::reload_model_instances()
{
bool invalidated = false;
@@ -461,7 +465,7 @@ bool Print::apply_config(DynamicPrintConfig config)
if (region_id < object->region_volumes.size() && ! object->region_volumes[region_id].empty())
invalidated |= object->invalidate_state_by_config_options(diff);
}
- other_region_configs.emplace_back(this_region_config);
+ other_region_configs.emplace_back(std::move(this_region_config));
}
}
}
@@ -953,6 +957,7 @@ bool Print::has_wipe_tower() const
void Print::_clear_wipe_tower()
{
m_tool_ordering.clear();
+ m_wipe_tower_priming.reset(nullptr);
m_wipe_tower_tool_changes.clear();
m_wipe_tower_final_purge.reset(nullptr);
}
@@ -963,7 +968,8 @@ void Print::_make_wipe_tower()
if (! this->has_wipe_tower())
return;
- m_tool_ordering = ToolOrdering(*this, (unsigned int)-1);
+ // Let the ToolOrdering class know there will be initial priming extrusions at the start of the print.
+ m_tool_ordering = ToolOrdering(*this, (unsigned int)-1, true);
unsigned int initial_extruder_id = m_tool_ordering.first_extruder();
if (initial_extruder_id == (unsigned int)-1 || m_tool_ordering.front().wipe_tower_partitions == 0)
// Don't generate any wipe tower.
@@ -977,7 +983,6 @@ void Print::_make_wipe_tower()
//wipe_tower.set_retract();
//wipe_tower.set_zhop();
- //wipe_tower.set_zhop();
// Set the extruder & material properties at the wipe tower object.
for (size_t i = 0; i < 4; ++ i)
@@ -987,6 +992,9 @@ void Print::_make_wipe_tower()
this->config.temperature.get_at(i),
this->config.first_layer_temperature.get_at(i));
+ m_wipe_tower_priming = Slic3r::make_unique<WipeTower::ToolChangeResult>(
+ wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), WipeTower::PURPOSE_EXTRUDE));
+
// Generate the wipe tower layers.
m_wipe_tower_tool_changes.reserve(m_tool_ordering.layer_tools().size());
unsigned int current_extruder_id = initial_extruder_id;
@@ -1048,7 +1056,7 @@ void Print::_make_wipe_tower()
wipe_tower.set_layer(float(m_tool_ordering.back().print_z), float(layer_height), 0, false, true);
}
m_wipe_tower_final_purge = Slic3r::make_unique<WipeTower::ToolChangeResult>(
- wipe_tower.tool_change(-1, false, WipeTower::PURPOSE_EXTRUDE));
+ wipe_tower.tool_change((unsigned int)-1, false, WipeTower::PURPOSE_EXTRUDE));
}
std::string Print::output_filename()
@@ -1080,4 +1088,9 @@ std::string Print::output_filepath(const std::string &path)
return path;
}
+void Print::set_status(int percent, const std::string &message)
+{
+ printf("Print::status %d => %s\n", percent, message.c_str());
+}
+
}
diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp
index 3b9b77982..bc8b17868 100644
--- a/xs/src/libslic3r/Print.hpp
+++ b/xs/src/libslic3r/Print.hpp
@@ -16,6 +16,8 @@
#include "GCode/ToolOrdering.hpp"
#include "GCode/WipeTower.hpp"
+#include "tbb/atomic.h"
+
namespace Slic3r {
class Print;
@@ -125,10 +127,10 @@ public:
// Slic3r::Point objects in scaled G-code coordinates in our coordinates
Points _shifted_copies;
- LayerPtrs layers;
- SupportLayerPtrs support_layers;
- PrintState<PrintObjectStep, posCount> state;
-
+ LayerPtrs layers;
+ SupportLayerPtrs support_layers;
+ PrintState<PrintObjectStep, posCount> state;
+
Print* print() { return this->_print; }
const Print* print() const { return this->_print; }
ModelObject* model_object() { return this->_model_object; }
@@ -231,14 +233,14 @@ public:
PrintRegionPtrs regions;
PlaceholderParser placeholder_parser;
// TODO: status_cb
- double total_used_filament, total_extruded_volume, total_cost, total_weight;
- std::map<size_t,float> filament_stats;
- PrintState<PrintStep, psCount> state;
+ double total_used_filament, total_extruded_volume, total_cost, total_weight;
+ std::map<size_t,float> filament_stats;
+ PrintState<PrintStep, psCount> state;
// ordered collections of extrusion paths to build skirt loops and brim
ExtrusionEntityCollection skirt, brim;
- Print() : total_used_filament(0), total_extruded_volume(0) {}
+ Print() : total_used_filament(0), total_extruded_volume(0) { restart(); }
~Print() { clear_objects(); }
// methods for handling objects
@@ -291,15 +293,28 @@ public:
// Cache it here, so it does not need to be recalculated during the G-code generation.
ToolOrdering m_tool_ordering;
// Cache of tool changes per print layer.
+ std::unique_ptr<WipeTower::ToolChangeResult> m_wipe_tower_priming;
std::vector<std::vector<WipeTower::ToolChangeResult>> m_wipe_tower_tool_changes;
std::unique_ptr<WipeTower::ToolChangeResult> m_wipe_tower_final_purge;
std::string output_filename();
std::string output_filepath(const std::string &path);
+
+ // Calls a registered callback to update the status.
+ void set_status(int percent, const std::string &message);
+ // Cancel the running computation. Stop execution of all the background threads.
+ void cancel() { m_canceled = true; }
+ // Cancel the running computation. Stop execution of all the background threads.
+ void restart() { m_canceled = false; }
+ // Has the calculation been canceled?
+ bool canceled() { return m_canceled; }
private:
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
PrintRegionConfig _region_config_from_model_volume(const ModelVolume &volume);
+
+ // Has the calculation been canceled?
+ tbb::atomic<bool> m_canceled;
};
#define FOREACH_BASE(type, container, iterator) for (type::const_iterator iterator = (container).begin(); iterator != (container).end(); ++iterator)
diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp
index 018d804de..6f9764b19 100644
--- a/xs/src/slic3r/GUI/3DScene.cpp
+++ b/xs/src/slic3r/GUI/3DScene.cpp
@@ -969,16 +969,23 @@ void _3DScene::_load_wipe_tower_toolpaths(
const float* color_tool(size_t tool) const { return tool_colors->data() + tool * 4; }
int volume_idx(int tool, int feature) const
{ return this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(tool, 0)) : feature; }
+
+ const std::vector<WipeTower::ToolChangeResult>& tool_change(size_t idx)
+ { return (idx == 0) ? priming : (idx == print->m_wipe_tower_tool_changes.size() + 1) ? final : print->m_wipe_tower_tool_changes[idx - 1]; }
+ std::vector<WipeTower::ToolChangeResult> priming;
+ std::vector<WipeTower::ToolChangeResult> final;
} ctxt;
ctxt.print = print;
ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
+ ctxt.priming.emplace_back(*print->m_wipe_tower_priming.get());
+ ctxt.final.emplace_back(*print->m_wipe_tower_final_purge.get());
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - start";
//FIXME Improve the heuristics for a grain size.
- size_t n_layers = print->m_wipe_tower_tool_changes.size();
- size_t grain_size = std::max(n_layers / 128, size_t(1));
+ size_t n_items = print->m_wipe_tower_tool_changes.size() + 1;
+ size_t grain_size = std::max(n_items / 128, size_t(1));
tbb::spin_mutex new_volume_mutex;
auto new_volume = [volumes, &new_volume_mutex](const float *color) -> GLVolume* {
auto *volume = new GLVolume(color);
@@ -988,21 +995,21 @@ void _3DScene::_load_wipe_tower_toolpaths(
return volume;
};
const size_t volumes_cnt_initial = volumes->volumes.size();
- std::vector<GLVolumeCollection> volumes_per_thread(n_layers);
+ std::vector<GLVolumeCollection> volumes_per_thread(n_items);
tbb::parallel_for(
- tbb::blocked_range<size_t>(0, n_layers, grain_size),
+ tbb::blocked_range<size_t>(0, n_items, grain_size),
[&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
// Bounding box of this slab of a wipe tower.
BoundingBoxf3 bbox;
bbox.min = Pointf3(
ctxt.print->config.wipe_tower_x.value - 10.,
ctxt.print->config.wipe_tower_y.value - 10.,
- ctxt.print->m_wipe_tower_tool_changes[range.begin()].front().print_z - 3.);
+ ctxt.tool_change(range.begin()).front().print_z - 3.);
bbox.max = Pointf3(
ctxt.print->config.wipe_tower_x.value + ctxt.print->config.wipe_tower_width.value + 10.,
ctxt.print->config.wipe_tower_y.value + ctxt.print->config.wipe_tower_per_color_wipe.value *
ctxt.print->m_tool_ordering.layer_tools()[range.begin()].wipe_tower_partitions + 10.,
- ctxt.print->m_wipe_tower_tool_changes[range.end() - 1].front().print_z + 0.1);
+ ctxt.tool_change(range.end() - 1).front().print_z + 0.1);
std::vector<GLVolume*> vols;
if (ctxt.color_by_tool()) {
for (size_t i = 0; i < ctxt.number_tools(); ++ i)
@@ -1015,7 +1022,7 @@ void _3DScene::_load_wipe_tower_toolpaths(
volume.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
}
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
- const std::vector<WipeTower::ToolChangeResult> &layer = ctxt.print->m_wipe_tower_tool_changes[idx_layer];
+ const std::vector<WipeTower::ToolChangeResult> &layer = ctxt.tool_change(idx_layer);
for (size_t i = 0; i < vols.size(); ++ i) {
GLVolume &vol = *vols[i];
if (vol.print_zs.empty() || vol.print_zs.back() != layer.front().print_z) {
diff --git a/xs/src/xsinit.h b/xs/src/xsinit.h
index 987912433..c375c7e62 100644
--- a/xs/src/xsinit.h
+++ b/xs/src/xsinit.h
@@ -31,6 +31,7 @@
#undef socketpair
#undef recvfrom
#undef sendto
+#undef pause
// these need to be included early for Win32 (listing it in Build.PL is not enough)
#include <ostream>