Port libvgcode from PrusaSlicer 2.8.0
Includes (but is not limited to) the following commits: SPE-2218 - libvgcode - Fixed color of wipe moves for speed range view SPE-2218 - libvgcode - Fixed detection of fan speed range SPE-2218 - libvgcode - Fixed detection of temperature range SPE-2218 - libvgcode - Fixed colors for Actual volumetric flow rate view SPE-2214 - Fixed detection of toolpaths bounding box in GCodeViewer SPE-2206 - Modified LibBGCode.cmake to get latest version of libbgcode which fixed parsing of gcode lines G4 libvgcode - Fixed potential out of bound access in ViewerImpl::update_view_full_range() Tech ENABLE_GL_CORE_PROFILE set as default Tech ENABLE_OPENGL_ES replaced by build option SLIC3R_OPENGL_ES libvgcode - Precompiler definition of ENABLE_OPENGL_ES moved into CMakeLists.txt Added missing include libvgcode - Textures setup modified to work when building using emscripten libvgcode - small optimization libvgcode - fixed OpenGLWrapper::unload_opengl() libvgcode - CMakeLists.txt modified to work with emscripten libvgcode - Replace 'glVertexAttribIPointer()' with 'glVertexAttribPointer()' in SegmentTemplate::init() for OpenGL ES libvgcode - Replace 'xor' with '^' Bitset.hpp libvgcode - Newer glad library for OpenGL 4.6 and OpenGL ES 3.0 libvgcode - Alternate fix in method ViewerImpl::update_heights_widths() for OpenGL ES libvgcode - Fixes in glAssertRecentCallImpl() libvgcode - Fixes in method ViewerImpl::update_heights_widths() for OpenGL ES Fixed ES shaders so they work with OpenGL ES 3.0 libvgcode - Use multiple plain textures in place of texture buffers for OpenGL ES libvgcode - Use plain textures in place of texture buffers for OpenGL ES (partial implementation using one texture per buffer) libvgcode - refactoring of class OpenGLWrapper libvgcode - small refactoring in shaders libvgcode - replacement of glMapBuffer() call for OpenGL ES Fixed warning libvgcode - Changes into CMakeLists.txt Fixed debug export of gcode data to be configuration indipendent Disabled tech ENABLE_NEW_GCODE_VIEWER_DEBUG Removed obsolete tech ENABLE_GCODE_VIEWER_DATA_CHECKING Code cleanup and techs removal - completed Code cleanup and techs removal - step 1 SPE-1872: Implemented G2/G3 lines discretization for gcfMarlinFirmware firmware flavour SPE-1872: Corrections into GCodeProcessor::process_G2_G3() to match firmware code SPE-1872: Actual speed profile - Further enhancements of imgui debug window SPE-1872: Actual speed profile - Rework in its calculation + enhanced imgui debug window SPE-1872: New imgui widget to show actual speed profile SPE-1872: Fixed actual speed for seam moves and at extrusion/travel/wipe start SPE-1872: Fixed rendering of wipe moves when actual speed view is selected SPE-1872: Actual speed profile extended to travel and wipe moves SPE-1872: Fixes in function recalculate_trapezoids() and method GCodeProcessor::TimeMachine::calculate_time() to smooth actual speed profile SPE-1872: Added debug graphic to show move actual speed profile SPE-1872: libvgcode library: replace volumetric flow rate data with mm3_per_mm to reduce memory usage SPE-1872: Added visualization of actual volumetric flow rate SPE-1872: Fixes in calculating actual speed SPE-1872: Added visualization of actual speed in gcode preview SPE-2124: Added command line option 'opengl-aa' to allow the user to turn on the automatic selection of max number of supported samples for OpenGL antialising #12117: Reduced moire patterns by using the highest number of samples available for multisampling New gcode visualization integration - Partially enabled imgui debug window New gcode visualization integration - Fixed center of gravity calculation and rendering New gcode visualization library - Interface for estimated times New gcode visualization library - Tool marker rendering New gcode visualization library - Axes aligned bounding boxes calculation Removed obsolete debug code New gcode visualization library - Added statistic of used memory New gcode visualization library - Separation of tool colors and color changes colors to simplify client code Added missing include New gcode visualization library - Added print color changes detection New gcode visualization library - Modified OpenGL ES context detection New gcode visualization library - Another makefile cleanup New gcode visualization library - Makefiles cleanup New gcode visualization library - Added suppression of error 'This function or variable may be unsafe' in VS2022 New gcode visualization library - Compatibility with OpenGL ES New gcode visualization library - Interface cleanup and documentation New gcode visualization library - Extended interface to give access to estimated times New gcode visualization integration - Toggling of top layer only view state New gcode visualization integration - Removed imperial units from tool position data Small refactoring New gcode visualization library - Custom values for travel and wipe moves radius New gcode visualization library - Allow customization of range colors New gcode visualization library - Partial update of interface comments/documentation New gcode visualization integration - Follow-up of 35ee55e29bb231fd01a2eb71ae293832a37ca65d - Better fix for toolpaths visible range when toggling options' visibility New gcode visualization integration - Fixed toolpaths reset New gcode visualization library - Fixed method set_option_color() New gcode visualization library - Fixed method ViewerImpl::set_extrusion_role_color() New gcode visualization library - Added methods to release gpu resources on demand. New gcode visualization library - Travel and wipe moves as options New gcode visualization integration - Fixed toolpaths visible range when toggling options' visibility New gcode visualization integration - Fixed management of gcode preview view type New gcode visualization - Fixed wrong include New gcode visualization - Added missing headers New gcode visualization - Refactoring + added missing headers New gcode visualization - New code set as standalone library + embed glad library to load OpenGL functions New gcode visualization - Fixed errors and warnings when building the new code as a standalone library New gcode visualization integration - Fixed layers ordering in pre-gcode preview New gcode visualization integration - Fixed objects' tool colors in pre-gcode preview Code cleanup New gcode visualization integration - Tool position properties data window New gcode visualization integration - Fixed in export toolpaths to obj New gcode visualization - Inlining in source code Refactoring New gcode visualization integration - Export toolpaths to obj Some refactoring and warning fix New gcode visualization integration - Customizable travel moves colors New gcode visualization integration - Customizable options colors New gcode visualization integration - Customizable extrusion roles colors New gcode visualization integration - Fixed pre-gcode preview layers times New gcode visualization integration - Modify pre-gcode preview to use the new toolpaths renderer, objects WIP New gcode visualization - Modify pre-gcode preview to use the new toolpaths renderer, WIP (brim/skirt/wipe tower) New gcode visualization integration - Do not reset visible range when toggling options/roles visibility New gcode visualization - Fixed color of first vertex of top layer (when top layer only option is enabled) New gcode visualization - Customizable travels and wipes segment radius New gcode visualization integration - Removed tech ENABLE_GCODE_VIEWER_STATISTICS New gcode visualization integration - Added check of OpenGL version New gcode visualization integration - Removed GCodeProcessorResult::spiral_vase_layers Another bunch of warnings fixes Fixed warnings New gcode visualization integration - Removal of old visualization Fixed includes New gcode visualization integration - File structure of new code separated in api + src New gcode visualization integration - View ranges management moved to new visualizer New gcode visualization integration - Fixed top layer only visualization for MMU printers New gcode visualization integration - Removed dependency on imgui from new visualizer Some refactoring New gcode visualization integration - Removed dependency on Slic3r::GCodeProcessorResult from new visualizer New gcode visualization integration - Moves' data conversion moved to client side New gcode visualization: layers times refactoring A bunch of fixes for the new gcode visualization New gcode visualization: render in gray color layers containing pause print or custom gcode options when in Color Print view New gcode visualization integration - Tool colors New gcode visualization integration - Layers times New gcode visualization integration - Travels and Extrusion roles times Fixed detection of start/end of contiguous extrusion paths New gcode visualization integration - Extrusion roles New gcode visualization integration - Colors New gcode visualization integration - Tool position Center of gravity and tool marker may both be rendered with fixed screen size and a scaling factor Fixed rendering of options in new gcode visualization Tool marker NOT rendered by the new visualization code Center of gravity marker NOT rendered by the new visualization code Fixed toolpaths_cog shaders Tool position window for new gcode visualization Top layer only coloring for neww gcode visualization Refactoring in preview's new visualization Hidden imgui debug dialog for new visualization in preview Synchronization of moves between old and new visualization Fixed missing gcode window in new visualization Rendering of debug imgui dialog moved from class libvgcode::Viewer to class libvgcode::Toolpaths + warnings fixing Some functionality moved from class libvgcode::Viewer to class libvgcode::Toolpaths Some refactoring and cleanup Refatoring of PathVertex and Toolpaths::load() SPE-1982: Tech ENABLE_NEW_GCODE_VIEWER - 1st installment of new toolpaths rendering code (WIP)
This commit is contained in:
800
src/slic3r/GUI/LibVGCode/LibVGCodeWrapper.cpp
Normal file
800
src/slic3r/GUI/LibVGCode/LibVGCodeWrapper.cpp
Normal file
@@ -0,0 +1,800 @@
|
||||
///|/ Copyright (c) Prusa Research 2020 - 2023 Enrico Turri @enricoturri1966
|
||||
///|/
|
||||
///|/ PrusaSlicer is released under the terms of the AGPLv3 or higher
|
||||
///|/
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <cassert>
|
||||
#include <cinttypes>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "LibVGCodeWrapper.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/Color.hpp"
|
||||
#include "libslic3r/CustomGCode.hpp"
|
||||
#include "libslic3r/Exception.hpp"
|
||||
#include "libslic3r/ExtrusionEntity.hpp"
|
||||
#include "libslic3r/ExtrusionEntityCollection.hpp"
|
||||
#include "libslic3r/GCode/WipeTower.hpp"
|
||||
#include "libslic3r/Layer.hpp"
|
||||
#include "libslic3r/Line.hpp"
|
||||
#include "libslic3r/Polyline.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "../../src/libvgcode/include/GCodeInputData.hpp"
|
||||
#include "../../src/libvgcode/include/PathVertex.hpp"
|
||||
#include "libvgcode/include/Types.hpp"
|
||||
|
||||
namespace libvgcode {
|
||||
class Viewer;
|
||||
|
||||
Vec3 convert(const Slic3r::Vec3f& v)
|
||||
{
|
||||
return { v.x(), v.y(), v.z() };
|
||||
}
|
||||
|
||||
Slic3r::Vec3f convert(const Vec3& v)
|
||||
{
|
||||
return { v[0], v[1], v[2] };
|
||||
}
|
||||
|
||||
Mat4x4 convert(const Slic3r::Matrix4f& m)
|
||||
{
|
||||
Mat4x4 ret;
|
||||
std::memcpy(ret.data(), m.data(), 16 * sizeof(float));
|
||||
return ret;
|
||||
}
|
||||
|
||||
Slic3r::ColorRGBA convert(const Color& c)
|
||||
{
|
||||
static const float inv_255 = 1.0f / 255.0f;
|
||||
return { c[0] * inv_255, c[1] * inv_255, c[2] * inv_255, 1.0f };
|
||||
}
|
||||
|
||||
Color convert(const Slic3r::ColorRGBA& c)
|
||||
{
|
||||
return { static_cast<uint8_t>(c.r() * 255.0f), static_cast<uint8_t>(c.g() * 255.0f), static_cast<uint8_t>(c.b() * 255.0f) };
|
||||
}
|
||||
|
||||
Color convert(const std::string& color_str)
|
||||
{
|
||||
Slic3r::ColorRGBA color_rgba;
|
||||
return decode_color(color_str, color_rgba) ? convert(color_rgba) : DUMMY_COLOR;
|
||||
}
|
||||
|
||||
Slic3r::ExtrusionRole convert(EGCodeExtrusionRole role)
|
||||
{
|
||||
switch (role)
|
||||
{
|
||||
case EGCodeExtrusionRole::None: { return Slic3r::ExtrusionRole::erNone; }
|
||||
case EGCodeExtrusionRole::Perimeter: { return Slic3r::ExtrusionRole::erPerimeter; }
|
||||
case EGCodeExtrusionRole::ExternalPerimeter: { return Slic3r::ExtrusionRole::erExternalPerimeter; }
|
||||
case EGCodeExtrusionRole::OverhangPerimeter: { return Slic3r::ExtrusionRole::erOverhangPerimeter; }
|
||||
case EGCodeExtrusionRole::InternalInfill: { return Slic3r::ExtrusionRole::erInternalInfill; }
|
||||
case EGCodeExtrusionRole::SolidInfill: { return Slic3r::ExtrusionRole::erSolidInfill; }
|
||||
case EGCodeExtrusionRole::TopSolidInfill: { return Slic3r::ExtrusionRole::erTopSolidInfill; }
|
||||
case EGCodeExtrusionRole::Ironing: { return Slic3r::ExtrusionRole::erIroning; }
|
||||
case EGCodeExtrusionRole::BridgeInfill: { return Slic3r::ExtrusionRole::erBridgeInfill; }
|
||||
case EGCodeExtrusionRole::GapFill: { return Slic3r::ExtrusionRole::erGapFill; }
|
||||
case EGCodeExtrusionRole::Skirt: { return Slic3r::ExtrusionRole::erSkirt; }
|
||||
case EGCodeExtrusionRole::SupportMaterial: { return Slic3r::ExtrusionRole::erSupportMaterial; }
|
||||
case EGCodeExtrusionRole::SupportMaterialInterface: { return Slic3r::ExtrusionRole::erSupportMaterialInterface; }
|
||||
case EGCodeExtrusionRole::WipeTower: { return Slic3r::ExtrusionRole::erWipeTower; }
|
||||
case EGCodeExtrusionRole::Custom: { return Slic3r::ExtrusionRole::erCustom; }
|
||||
default: { return Slic3r::ExtrusionRole::erNone; }
|
||||
}
|
||||
}
|
||||
|
||||
EGCodeExtrusionRole convert(Slic3r::ExtrusionRole role)
|
||||
{
|
||||
switch (role)
|
||||
{
|
||||
case Slic3r::ExtrusionRole::erNone: { return EGCodeExtrusionRole::None; }
|
||||
case Slic3r::ExtrusionRole::erPerimeter: { return EGCodeExtrusionRole::Perimeter; }
|
||||
case Slic3r::ExtrusionRole::erExternalPerimeter: { return EGCodeExtrusionRole::ExternalPerimeter; }
|
||||
case Slic3r::ExtrusionRole::erOverhangPerimeter: { return EGCodeExtrusionRole::OverhangPerimeter; }
|
||||
case Slic3r::ExtrusionRole::erInternalInfill: { return EGCodeExtrusionRole::InternalInfill; }
|
||||
case Slic3r::ExtrusionRole::erSolidInfill: { return EGCodeExtrusionRole::SolidInfill; }
|
||||
case Slic3r::ExtrusionRole::erTopSolidInfill: { return EGCodeExtrusionRole::TopSolidInfill; }
|
||||
case Slic3r::ExtrusionRole::erIroning: { return EGCodeExtrusionRole::Ironing; }
|
||||
case Slic3r::ExtrusionRole::erBridgeInfill: { return EGCodeExtrusionRole::BridgeInfill; }
|
||||
case Slic3r::ExtrusionRole::erGapFill: { return EGCodeExtrusionRole::GapFill; }
|
||||
case Slic3r::ExtrusionRole::erSkirt: { return EGCodeExtrusionRole::Skirt; }
|
||||
case Slic3r::ExtrusionRole::erSupportMaterial: { return EGCodeExtrusionRole::SupportMaterial; }
|
||||
case Slic3r::ExtrusionRole::erSupportMaterialInterface: { return EGCodeExtrusionRole::SupportMaterialInterface; }
|
||||
case Slic3r::ExtrusionRole::erWipeTower: { return EGCodeExtrusionRole::WipeTower; }
|
||||
case Slic3r::ExtrusionRole::erCustom: { return EGCodeExtrusionRole::Custom; }
|
||||
default: { return EGCodeExtrusionRole::None; }
|
||||
}
|
||||
}
|
||||
|
||||
EMoveType convert(Slic3r::EMoveType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Slic3r::EMoveType::Noop: { return EMoveType::Noop; }
|
||||
case Slic3r::EMoveType::Retract: { return EMoveType::Retract; }
|
||||
case Slic3r::EMoveType::Unretract: { return EMoveType::Unretract; }
|
||||
case Slic3r::EMoveType::Seam: { return EMoveType::Seam; }
|
||||
case Slic3r::EMoveType::Tool_change: { return EMoveType::ToolChange; }
|
||||
case Slic3r::EMoveType::Color_change: { return EMoveType::ColorChange; }
|
||||
case Slic3r::EMoveType::Pause_Print: { return EMoveType::PausePrint; }
|
||||
case Slic3r::EMoveType::Custom_GCode: { return EMoveType::CustomGCode; }
|
||||
case Slic3r::EMoveType::Travel: { return EMoveType::Travel; }
|
||||
case Slic3r::EMoveType::Wipe: { return EMoveType::Wipe; }
|
||||
case Slic3r::EMoveType::Extrude: { return EMoveType::Extrude; }
|
||||
default: { return EMoveType::COUNT; }
|
||||
}
|
||||
}
|
||||
|
||||
// EOptionType convert(const Slic3r::GUI::Preview::OptionType& type)
|
||||
// {
|
||||
// switch (type)
|
||||
// {
|
||||
// case Slic3r::GUI::Preview::OptionType::Travel: { return EOptionType::Travels; }
|
||||
// case Slic3r::GUI::Preview::OptionType::Wipe: { return EOptionType::Wipes; }
|
||||
// case Slic3r::GUI::Preview::OptionType::Retractions: { return EOptionType::Retractions; }
|
||||
// case Slic3r::GUI::Preview::OptionType::Unretractions: { return EOptionType::Unretractions; }
|
||||
// case Slic3r::GUI::Preview::OptionType::Seams: { return EOptionType::Seams; }
|
||||
// case Slic3r::GUI::Preview::OptionType::ToolChanges: { return EOptionType::ToolChanges; }
|
||||
// case Slic3r::GUI::Preview::OptionType::ColorChanges: { return EOptionType::ColorChanges; }
|
||||
// case Slic3r::GUI::Preview::OptionType::PausePrints: { return EOptionType::PausePrints; }
|
||||
// case Slic3r::GUI::Preview::OptionType::CustomGCodes: { return EOptionType::CustomGCodes; }
|
||||
// #if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
|
||||
// case Slic3r::GUI::Preview::OptionType::CenterOfGravity: { return EOptionType::CenterOfGravity; }
|
||||
// case Slic3r::GUI::Preview::OptionType::ToolMarker: { return EOptionType::ToolMarker; }
|
||||
// #else
|
||||
// // case Slic3r::GUI::Preview::OptionType::CenterOfGravity: { return EOptionType::COUNT; }
|
||||
// case Slic3r::GUI::Preview::OptionType::ToolMarker: { return EOptionType::COUNT; }
|
||||
// #endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
|
||||
// default: { return EOptionType::COUNT; }
|
||||
// }
|
||||
// }
|
||||
|
||||
ETimeMode convert(const Slic3r::PrintEstimatedStatistics::ETimeMode& mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case Slic3r::PrintEstimatedStatistics::ETimeMode::Normal: { return ETimeMode::Normal; }
|
||||
case Slic3r::PrintEstimatedStatistics::ETimeMode::Stealth: { return ETimeMode::Stealth; }
|
||||
default: { return ETimeMode::COUNT; }
|
||||
}
|
||||
}
|
||||
|
||||
Slic3r::PrintEstimatedStatistics::ETimeMode convert(const ETimeMode& mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case ETimeMode::Normal: { return Slic3r::PrintEstimatedStatistics::ETimeMode::Normal; }
|
||||
case ETimeMode::Stealth: { return Slic3r::PrintEstimatedStatistics::ETimeMode::Stealth; }
|
||||
default: { return Slic3r::PrintEstimatedStatistics::ETimeMode::Count; }
|
||||
}
|
||||
}
|
||||
|
||||
GCodeInputData convert(const Slic3r::GCodeProcessorResult& result, const std::vector<std::string>& str_tool_colors,
|
||||
const std::vector<std::string>& str_color_print_colors, const Viewer& viewer)
|
||||
{
|
||||
GCodeInputData ret;
|
||||
|
||||
// collect tool colors
|
||||
ret.tools_colors.reserve(str_tool_colors.size());
|
||||
for (const std::string& color : str_tool_colors) {
|
||||
ret.tools_colors.emplace_back(convert(color));
|
||||
}
|
||||
|
||||
// collect color print colors
|
||||
const std::vector<std::string>& str_colors = str_color_print_colors.empty() ? str_tool_colors : str_color_print_colors;
|
||||
ret.color_print_colors.reserve(str_colors.size());
|
||||
for (const std::string& color : str_colors) {
|
||||
ret.color_print_colors.emplace_back(convert(color));
|
||||
}
|
||||
|
||||
const std::vector<Slic3r::GCodeProcessorResult::MoveVertex>& moves = result.moves;
|
||||
ret.vertices.reserve(2 * moves.size());
|
||||
for (size_t i = 1; i < moves.size(); ++i) {
|
||||
const Slic3r::GCodeProcessorResult::MoveVertex& curr = moves[i];
|
||||
const Slic3r::GCodeProcessorResult::MoveVertex& prev = moves[i - 1];
|
||||
const EMoveType curr_type = convert(curr.type);
|
||||
const EOptionType option_type = move_type_to_option(curr_type);
|
||||
if (option_type == EOptionType::COUNT || option_type == EOptionType::Travels || option_type == EOptionType::Wipes) {
|
||||
if (ret.vertices.empty() || prev.type != curr.type || prev.extrusion_role != curr.extrusion_role) {
|
||||
// to allow libvgcode to properly detect the start/end of a path we need to add a 'phantom' vertex
|
||||
// equal to the current one with the exception of the position, which should match the previous move position,
|
||||
// and the times, which are set to zero
|
||||
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
|
||||
const libvgcode::PathVertex vertex = { convert(prev.position), curr.height, curr.width, curr.feedrate, prev.actual_feedrate,
|
||||
curr.mm3_per_mm, curr.fan_speed, curr.temperature, 0.0f, convert(curr.extrusion_role), curr_type,
|
||||
static_cast<uint32_t>(curr.gcode_id), static_cast<uint32_t>(curr.layer_id),
|
||||
static_cast<uint8_t>(curr.extruder_id), static_cast<uint8_t>(curr.cp_color_id), { 0.0f, 0.0f } };
|
||||
#else
|
||||
const libvgcode::PathVertex vertex = { convert(prev.position), curr.height, curr.width, curr.feedrate, prev.actual_feedrate,
|
||||
curr.mm3_per_mm, curr.fan_speed, curr.temperature, convert(curr.extrusion_role), curr_type,
|
||||
static_cast<uint32_t>(curr.gcode_id), static_cast<uint32_t>(curr.layer_id),
|
||||
static_cast<uint8_t>(curr.extruder_id), static_cast<uint8_t>(curr.cp_color_id), { 0.0f, 0.0f } };
|
||||
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
|
||||
ret.vertices.emplace_back(vertex);
|
||||
}
|
||||
}
|
||||
|
||||
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
|
||||
const libvgcode::PathVertex vertex = { convert(curr.position), curr.height, curr.width, curr.feedrate, curr.actual_feedrate,
|
||||
curr.mm3_per_mm, curr.fan_speed, curr.temperature,
|
||||
result.filament_densities[curr.extruder_id] * curr.mm3_per_mm * (curr.position - prev.position).norm(),
|
||||
convert(curr.extrusion_role), curr_type, static_cast<uint32_t>(curr.gcode_id), static_cast<uint32_t>(curr.layer_id),
|
||||
static_cast<uint8_t>(curr.extruder_id), static_cast<uint8_t>(curr.cp_color_id), curr.time };
|
||||
#else
|
||||
const libvgcode::PathVertex vertex = { convert(curr.position), curr.height, curr.width, curr.feedrate, curr.actual_feedrate,
|
||||
curr.mm3_per_mm, curr.fan_speed, curr.temperature, convert(curr.extrusion_role), curr_type,
|
||||
static_cast<uint32_t>(curr.gcode_id), static_cast<uint32_t>(curr.layer_id),
|
||||
static_cast<uint8_t>(curr.extruder_id), static_cast<uint8_t>(curr.cp_color_id), curr.time };
|
||||
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
|
||||
ret.vertices.emplace_back(vertex);
|
||||
}
|
||||
ret.vertices.shrink_to_fit();
|
||||
|
||||
ret.spiral_vase_mode = result.spiral_vase_mode;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void convert_lines_to_vertices(const Slic3r::Lines& lines, const std::vector<float>& widths, const std::vector<float>& heights,
|
||||
float top_z, size_t layer_id, size_t extruder_id, size_t color_id, EGCodeExtrusionRole extrusion_role, bool closed, std::vector<PathVertex>& vertices)
|
||||
{
|
||||
if (lines.empty())
|
||||
return;
|
||||
|
||||
// loop once more in case of closed loops
|
||||
const size_t lines_end = closed ? (lines.size() + 1) : lines.size();
|
||||
for (size_t ii = 0; ii < lines_end; ++ii) {
|
||||
const size_t i = (ii == lines.size()) ? 0 : ii;
|
||||
const Slic3r::Line& line = lines[i];
|
||||
// first segment of the polyline
|
||||
if (ii == 0) {
|
||||
// add a dummy vertex at the start, to separate the current line from the others
|
||||
const Slic3r::Vec2f a = unscale(line.a).cast<float>();
|
||||
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
|
||||
libvgcode::PathVertex vertex = { convert(Slic3r::Vec3f(a.x(), a.y(), top_z)), heights[i], widths[i], 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, extrusion_role, EMoveType::Noop, 0, static_cast<uint32_t>(layer_id),
|
||||
static_cast<uint8_t>(extruder_id), static_cast<uint8_t>(color_id), { 0.0f, 0.0f } };
|
||||
#else
|
||||
libvgcode::PathVertex vertex = { convert(Slic3r::Vec3f(a.x(), a.y(), top_z)), heights[i], widths[i], 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, extrusion_role, EMoveType::Noop, 0, static_cast<uint32_t>(layer_id),
|
||||
static_cast<uint8_t>(extruder_id), static_cast<uint8_t>(color_id), { 0.0f, 0.0f } };
|
||||
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
|
||||
vertices.emplace_back(vertex);
|
||||
// add the starting vertex of the segment
|
||||
vertex.type = EMoveType::Extrude;
|
||||
vertices.emplace_back(vertex);
|
||||
}
|
||||
// add the ending vertex of the segment
|
||||
const Slic3r::Vec2f b = unscale(line.b).cast<float>();
|
||||
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
|
||||
const libvgcode::PathVertex vertex = { convert(Slic3r::Vec3f(b.x(), b.y(), top_z)), heights[i], widths[i], 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, extrusion_role, EMoveType::Extrude, 0, static_cast<uint32_t>(layer_id),
|
||||
static_cast<uint8_t>(extruder_id), static_cast<uint8_t>(color_id), { 0.0f, 0.0f } };
|
||||
#else
|
||||
const libvgcode::PathVertex vertex = { convert(Slic3r::Vec3f(b.x(), b.y(), top_z)), heights[i], widths[i], 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, extrusion_role, EMoveType::Extrude, 0, static_cast<uint32_t>(layer_id),
|
||||
static_cast<uint8_t>(extruder_id), static_cast<uint8_t>(color_id), { 0.0f, 0.0f } };
|
||||
#endif // VGCODE_ENABLE_COG_AND_TOOL_MARKERS
|
||||
vertices.emplace_back(vertex);
|
||||
}
|
||||
}
|
||||
|
||||
static void convert_to_vertices(const Slic3r::ExtrusionPath& extrusion_path, float print_z, size_t layer_id, size_t extruder_id, size_t color_id,
|
||||
EGCodeExtrusionRole extrusion_role, const Slic3r::Point& shift, std::vector<PathVertex>& vertices)
|
||||
{
|
||||
Slic3r::Polyline polyline = extrusion_path.polyline;
|
||||
polyline.remove_duplicate_points();
|
||||
polyline.translate(shift);
|
||||
const Slic3r::Lines lines = polyline.lines();
|
||||
std::vector<float> widths(lines.size(), extrusion_path.width);
|
||||
std::vector<float> heights(lines.size(), extrusion_path.height);
|
||||
convert_lines_to_vertices(lines, widths, heights, print_z, layer_id, extruder_id, color_id, extrusion_role, false, vertices);
|
||||
}
|
||||
|
||||
static void convert_to_vertices(const Slic3r::ExtrusionMultiPath& extrusion_multi_path, float print_z, size_t layer_id, size_t extruder_id,
|
||||
size_t color_id, EGCodeExtrusionRole extrusion_role, const Slic3r::Point& shift, std::vector<PathVertex>& vertices)
|
||||
{
|
||||
Slic3r::Lines lines;
|
||||
std::vector<float> widths;
|
||||
std::vector<float> heights;
|
||||
for (const Slic3r::ExtrusionPath& extrusion_path : extrusion_multi_path.paths) {
|
||||
Slic3r::Polyline polyline = extrusion_path.polyline;
|
||||
polyline.remove_duplicate_points();
|
||||
polyline.translate(shift);
|
||||
const Slic3r::Lines lines_this = polyline.lines();
|
||||
append(lines, lines_this);
|
||||
widths.insert(widths.end(), lines_this.size(), extrusion_path.width);
|
||||
heights.insert(heights.end(), lines_this.size(), extrusion_path.height);
|
||||
}
|
||||
convert_lines_to_vertices(lines, widths, heights, print_z, layer_id, extruder_id, color_id, extrusion_role, false, vertices);
|
||||
}
|
||||
|
||||
static void convert_to_vertices(const Slic3r::ExtrusionLoop& extrusion_loop, float print_z, size_t layer_id, size_t extruder_id, size_t color_id,
|
||||
EGCodeExtrusionRole extrusion_role, const Slic3r::Point& shift, std::vector<PathVertex>& vertices)
|
||||
{
|
||||
Slic3r::Lines lines;
|
||||
std::vector<float> widths;
|
||||
std::vector<float> heights;
|
||||
for (const Slic3r::ExtrusionPath& extrusion_path : extrusion_loop.paths) {
|
||||
Slic3r::Polyline polyline = extrusion_path.polyline;
|
||||
polyline.remove_duplicate_points();
|
||||
polyline.translate(shift);
|
||||
const Slic3r::Lines lines_this = polyline.lines();
|
||||
append(lines, lines_this);
|
||||
widths.insert(widths.end(), lines_this.size(), extrusion_path.width);
|
||||
heights.insert(heights.end(), lines_this.size(), extrusion_path.height);
|
||||
}
|
||||
convert_lines_to_vertices(lines, widths, heights, print_z, layer_id, extruder_id, color_id, extrusion_role, true, vertices);
|
||||
}
|
||||
|
||||
// forward declaration
|
||||
static void convert_to_vertices(const Slic3r::ExtrusionEntityCollection& extrusion_entity_collection, float print_z, size_t layer_id,
|
||||
size_t extruder_id, size_t color_id, EGCodeExtrusionRole extrusion_role, const Slic3r::Point& shift, std::vector<PathVertex>& vertices);
|
||||
|
||||
static void convert_to_vertices(const Slic3r::ExtrusionEntity& extrusion_entity, float print_z, size_t layer_id, size_t extruder_id, size_t color_id,
|
||||
EGCodeExtrusionRole extrusion_role, const Slic3r::Point& shift, std::vector<PathVertex>& vertices)
|
||||
{
|
||||
auto* extrusion_path = dynamic_cast<const Slic3r::ExtrusionPath*>(&extrusion_entity);
|
||||
if (extrusion_path != nullptr)
|
||||
convert_to_vertices(*extrusion_path, print_z, layer_id, extruder_id, color_id, extrusion_role, shift, vertices);
|
||||
else {
|
||||
auto* extrusion_loop = dynamic_cast<const Slic3r::ExtrusionLoop*>(&extrusion_entity);
|
||||
if (extrusion_loop != nullptr)
|
||||
convert_to_vertices(*extrusion_loop, print_z, layer_id, extruder_id, color_id, extrusion_role, shift, vertices);
|
||||
else {
|
||||
auto* extrusion_multi_path = dynamic_cast<const Slic3r::ExtrusionMultiPath*>(&extrusion_entity);
|
||||
if (extrusion_multi_path != nullptr)
|
||||
convert_to_vertices(*extrusion_multi_path, print_z, layer_id, extruder_id, color_id, extrusion_role, shift, vertices);
|
||||
else {
|
||||
auto* extrusion_entity_collection = dynamic_cast<const Slic3r::ExtrusionEntityCollection*>(&extrusion_entity);
|
||||
if (extrusion_entity_collection != nullptr)
|
||||
convert_to_vertices(*extrusion_entity_collection, print_z, layer_id, extruder_id, color_id, extrusion_role, shift, vertices);
|
||||
else
|
||||
throw Slic3r::RuntimeError("Found unexpected extrusion_entity type");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void convert_to_vertices(const Slic3r::ExtrusionEntityCollection& extrusion_entity_collection, float print_z, size_t layer_id,
|
||||
size_t extruder_id, size_t color_id, EGCodeExtrusionRole extrusion_role, const Slic3r::Point& shift, std::vector<PathVertex>& vertices)
|
||||
{
|
||||
for (const Slic3r::ExtrusionEntity* extrusion_entity : extrusion_entity_collection.entities) {
|
||||
if (extrusion_entity != nullptr)
|
||||
convert_to_vertices(*extrusion_entity, print_z, layer_id, extruder_id, color_id, extrusion_role, shift, vertices);
|
||||
}
|
||||
}
|
||||
|
||||
struct VerticesData
|
||||
{
|
||||
std::vector<PathVertex> vertices;
|
||||
std::vector<float> layers_zs;
|
||||
};
|
||||
|
||||
static void convert_brim_skirt_to_vertices(const Slic3r::Print& print, std::vector<VerticesData>& vertices_data)
|
||||
{
|
||||
vertices_data.emplace_back(VerticesData());
|
||||
VerticesData& data = vertices_data.back();
|
||||
|
||||
// number of skirt layers
|
||||
size_t total_layer_count = 0;
|
||||
for (const Slic3r::PrintObject* print_object : print.objects()) {
|
||||
total_layer_count = std::max(total_layer_count, print_object->total_layer_count());
|
||||
}
|
||||
size_t skirt_height = print.has_infinite_skirt() ? total_layer_count : std::min<size_t>(print.config().skirt_height.value, total_layer_count);
|
||||
if (skirt_height == 0 && print.has_brim())
|
||||
skirt_height = 1;
|
||||
|
||||
// Get first skirt_height layers.
|
||||
//FIXME This code is fishy. It may not work for multiple objects with different layering due to variable layer height feature.
|
||||
// This is not critical as this is just an initial preview.
|
||||
const Slic3r::PrintObject* highest_object = *std::max_element(print.objects().begin(), print.objects().end(),
|
||||
[](auto l, auto r) { return l->layers().size() < r->layers().size(); });
|
||||
data.layers_zs.reserve(skirt_height * 2);
|
||||
for (size_t i = 0; i < std::min(skirt_height, highest_object->layers().size()); ++i) {
|
||||
data.layers_zs.emplace_back(float(highest_object->layers()[i]->print_z));
|
||||
}
|
||||
// Only add skirt for the raft layers.
|
||||
for (size_t i = 0; i < std::min(skirt_height, std::min(highest_object->slicing_parameters().raft_layers(), highest_object->support_layers().size())); ++i) {
|
||||
data.layers_zs.emplace_back(float(highest_object->support_layers()[i]->print_z));
|
||||
}
|
||||
Slic3r::sort_remove_duplicates(data.layers_zs);
|
||||
skirt_height = std::min(skirt_height, data.layers_zs.size());
|
||||
data.layers_zs.erase(data.layers_zs.begin() + skirt_height, data.layers_zs.end());
|
||||
|
||||
for (size_t i = 0; i < skirt_height; ++i) {
|
||||
// TODO - brim map?
|
||||
// if (i == 0)
|
||||
// convert_to_vertices(print.brim(), data.layers_zs[i], i, 0, 0, EGCodeExtrusionRole::Skirt, Slic3r::Point(0, 0), data.vertices);
|
||||
convert_to_vertices(print.skirt(), data.layers_zs[i], i, 0, 0, EGCodeExtrusionRole::Skirt, Slic3r::Point(0, 0), data.vertices);
|
||||
}
|
||||
}
|
||||
|
||||
class WipeTowerHelper
|
||||
{
|
||||
public:
|
||||
WipeTowerHelper(const Slic3r::Print& print) : m_print(print) {
|
||||
const Slic3r::PrintConfig& config = m_print.config();
|
||||
const Slic3r::WipeTowerData& wipe_tower_data = m_print.wipe_tower_data();
|
||||
if (wipe_tower_data.priming && config.single_extruder_multi_material_priming) {
|
||||
for (size_t i = 0; i < wipe_tower_data.priming.get()->size(); ++i) {
|
||||
m_priming.emplace_back(wipe_tower_data.priming.get()->at(i));
|
||||
}
|
||||
}
|
||||
if (wipe_tower_data.final_purge)
|
||||
m_final.emplace_back(*wipe_tower_data.final_purge.get());
|
||||
|
||||
m_angle = print.model().wipe_tower.rotation / 180.0f * PI;
|
||||
// ORCA/BBS: plate index
|
||||
m_position = print.model().wipe_tower.positions[print.get_plate_index()].cast<float>();
|
||||
m_layers_count = wipe_tower_data.tool_changes.size() + (m_priming.empty() ? 0 : 1);
|
||||
}
|
||||
|
||||
const std::vector<Slic3r::WipeTower::ToolChangeResult>& tool_change(size_t idx) {
|
||||
const auto& tool_changes = m_print.wipe_tower_data().tool_changes;
|
||||
return m_priming.empty() ?
|
||||
((idx == tool_changes.size()) ? m_final : tool_changes[idx]) :
|
||||
((idx == 0) ? m_priming : (idx == tool_changes.size() + 1) ? m_final : tool_changes[idx - 1]);
|
||||
}
|
||||
|
||||
float get_angle() const { return m_angle; }
|
||||
const Slic3r::Vec2f& get_position() const { return m_position; }
|
||||
size_t get_layers_count() { return m_layers_count; }
|
||||
|
||||
private:
|
||||
const Slic3r::Print& m_print;
|
||||
std::vector<Slic3r::WipeTower::ToolChangeResult> m_priming;
|
||||
std::vector<Slic3r::WipeTower::ToolChangeResult> m_final;
|
||||
Slic3r::Vec2f m_position{ Slic3r::Vec2f::Zero() };
|
||||
float m_angle{ 0.0f };
|
||||
size_t m_layers_count{ 0 };
|
||||
};
|
||||
|
||||
static void convert_wipe_tower_to_vertices(const Slic3r::Print& print, const std::vector<std::string>& str_tool_colors,
|
||||
std::vector<VerticesData>& vertices_data)
|
||||
{
|
||||
vertices_data.emplace_back(VerticesData());
|
||||
VerticesData& data = vertices_data.back();
|
||||
|
||||
WipeTowerHelper wipe_tower_helper(print);
|
||||
const float angle = wipe_tower_helper.get_angle();
|
||||
const Slic3r::Vec2f& position = wipe_tower_helper.get_position();
|
||||
|
||||
for (size_t item = 0; item < wipe_tower_helper.get_layers_count(); ++item) {
|
||||
const std::vector<Slic3r::WipeTower::ToolChangeResult>& layer = wipe_tower_helper.tool_change(item);
|
||||
for (const Slic3r::WipeTower::ToolChangeResult& extrusions : layer) {
|
||||
data.layers_zs.emplace_back(extrusions.print_z);
|
||||
for (size_t i = 1; i < extrusions.extrusions.size(); /*no increment*/) {
|
||||
const Slic3r::WipeTower::Extrusion& e = extrusions.extrusions[i];
|
||||
if (e.width == 0.0f) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
size_t j = i + 1;
|
||||
if (str_tool_colors.empty())
|
||||
for (; j < extrusions.extrusions.size() && extrusions.extrusions[j].width > 0.0f; ++j);
|
||||
else
|
||||
for (; j < extrusions.extrusions.size() && extrusions.extrusions[j].tool == e.tool && extrusions.extrusions[j].width > 0.0f; ++j);
|
||||
|
||||
const size_t n_lines = j - i;
|
||||
Slic3r::Lines lines;
|
||||
std::vector<float> widths;
|
||||
std::vector<float> heights;
|
||||
lines.reserve(n_lines);
|
||||
widths.reserve(n_lines);
|
||||
heights.assign(n_lines, extrusions.layer_height);
|
||||
Slic3r::WipeTower::Extrusion e_prev = extrusions.extrusions[i - 1];
|
||||
|
||||
if (!extrusions.priming) { // wipe tower extrusions describe the wipe tower at the origin with no rotation
|
||||
e_prev.pos = Eigen::Rotation2Df(angle) * e_prev.pos;
|
||||
e_prev.pos += position;
|
||||
}
|
||||
|
||||
for (; i < j; ++i) {
|
||||
Slic3r::WipeTower::Extrusion ee = extrusions.extrusions[i];
|
||||
assert(ee.width > 0.0f);
|
||||
if (!extrusions.priming) {
|
||||
ee.pos = Eigen::Rotation2Df(angle) * ee.pos;
|
||||
ee.pos += position;
|
||||
}
|
||||
lines.emplace_back(Slic3r::Point::new_scale(e_prev.pos.x(), e_prev.pos.y()), Slic3r::Point::new_scale(ee.pos.x(), ee.pos.y()));
|
||||
widths.emplace_back(ee.width);
|
||||
e_prev = ee;
|
||||
}
|
||||
|
||||
convert_lines_to_vertices(lines, widths, heights, extrusions.print_z, item, static_cast<size_t>(e.tool), 0,
|
||||
EGCodeExtrusionRole::WipeTower, lines.front().a == lines.back().b, data.vertices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Slic3r::sort_remove_duplicates(data.layers_zs);
|
||||
}
|
||||
|
||||
class ObjectHelper
|
||||
{
|
||||
public:
|
||||
ObjectHelper(const std::vector<Slic3r::CustomGCode::Item>& color_print_values, size_t tool_colors_count, size_t color_print_colors_count, size_t extruders_count)
|
||||
: m_color_print_values(color_print_values)
|
||||
, m_tool_colors_count(tool_colors_count)
|
||||
, m_color_print_colors_count(color_print_colors_count)
|
||||
, m_extruders_count(extruders_count) {
|
||||
}
|
||||
|
||||
uint8_t color_id(float print_z, size_t extruder_id) const {
|
||||
if (!m_color_print_values.empty())
|
||||
return color_print_color_id(double(print_z), extruder_id);
|
||||
else {
|
||||
if (m_tool_colors_count > 0)
|
||||
return std::min<uint8_t>(m_tool_colors_count - 1, static_cast<uint8_t>(extruder_id));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const std::vector<Slic3r::CustomGCode::Item>& m_color_print_values;
|
||||
size_t m_tool_colors_count{ 0 };
|
||||
size_t m_color_print_colors_count{ 0 };
|
||||
size_t m_extruders_count{ 0 };
|
||||
|
||||
uint8_t color_print_color_id(double print_z, size_t extruder_id) const {
|
||||
auto it = std::find_if(m_color_print_values.begin(), m_color_print_values.end(),
|
||||
[print_z](const Slic3r::CustomGCode::Item& code) {
|
||||
return std::fabs(code.print_z - print_z) < EPSILON;
|
||||
});
|
||||
if (it != m_color_print_values.end()) {
|
||||
Slic3r::CustomGCode::Type type = it->type;
|
||||
// pause print or custom Gcode
|
||||
if (type == Slic3r::CustomGCode::PausePrint || (type != Slic3r::CustomGCode::ColorChange && type != Slic3r::CustomGCode::Template))
|
||||
return static_cast<uint8_t>(m_color_print_colors_count - 1); // last color item is a gray color for pause print or custom G-code
|
||||
switch (it->type) {
|
||||
// change color for current extruder
|
||||
case Slic3r::CustomGCode::ColorChange: {
|
||||
const int c = color_change_color_id(it, extruder_id);
|
||||
if (c >= 0)
|
||||
return static_cast<uint8_t>(c);
|
||||
break;
|
||||
}
|
||||
// change tool (extruder)
|
||||
case Slic3r::CustomGCode::ToolChange: { return tool_change_color_id(it, extruder_id); }
|
||||
default: { break; }
|
||||
}
|
||||
}
|
||||
|
||||
const Slic3r::CustomGCode::Item value{ print_z + EPSILON, Slic3r::CustomGCode::Custom, 0, "" };
|
||||
it = std::lower_bound(m_color_print_values.begin(), m_color_print_values.end(), value);
|
||||
while (it != m_color_print_values.begin()) {
|
||||
--it;
|
||||
switch (it->type) {
|
||||
// change color for current extruder
|
||||
case Slic3r::CustomGCode::ColorChange: {
|
||||
const int c = color_change_color_id(it, extruder_id);
|
||||
if (c >= 0)
|
||||
return static_cast<uint8_t>(c);
|
||||
break;
|
||||
}
|
||||
// change tool (extruder)
|
||||
case Slic3r::CustomGCode::ToolChange: { return tool_change_color_id(it, extruder_id); }
|
||||
default: { break; }
|
||||
}
|
||||
}
|
||||
|
||||
return std::min<uint8_t>(m_extruders_count - 1, static_cast<uint8_t>(extruder_id));
|
||||
}
|
||||
|
||||
int color_change_color_id(std::vector<Slic3r::CustomGCode::Item>::const_iterator it, size_t extruder_id) const {
|
||||
if (m_extruders_count == 1)
|
||||
return m600_color_id(it);
|
||||
|
||||
auto it_n = it;
|
||||
bool is_tool_change = false;
|
||||
while (it_n != m_color_print_values.begin()) {
|
||||
--it_n;
|
||||
if (it_n->type == Slic3r::CustomGCode::ToolChange) {
|
||||
is_tool_change = true;
|
||||
if (it_n->extruder == it->extruder || (it_n->extruder == 0 && it->extruder == static_cast<int>(extruder_id + 1)))
|
||||
return m600_color_id(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!is_tool_change && it->extruder == static_cast<int>(extruder_id + 1))
|
||||
return m600_color_id(it);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t tool_change_color_id(std::vector<Slic3r::CustomGCode::Item>::const_iterator it, size_t extruder_id) const {
|
||||
const int current_extruder = it->extruder == 0 ? static_cast<int>(extruder_id + 1) : it->extruder;
|
||||
if (m_tool_colors_count == m_extruders_count + 1) // there is no one "M600"
|
||||
return std::min<uint8_t>(m_extruders_count - 1, std::max<uint8_t>(current_extruder - 1, 0));
|
||||
|
||||
auto it_n = it;
|
||||
while (it_n != m_color_print_values.begin()) {
|
||||
--it_n;
|
||||
if (it_n->type == Slic3r::CustomGCode::ColorChange && it_n->extruder == current_extruder)
|
||||
return m600_color_id(it_n);
|
||||
}
|
||||
|
||||
return std::min<uint8_t>(m_extruders_count - 1, std::max<uint8_t>(current_extruder - 1, 0));
|
||||
}
|
||||
|
||||
int m600_color_id(std::vector<Slic3r::CustomGCode::Item>::const_iterator it) const {
|
||||
int shift = 0;
|
||||
while (it != m_color_print_values.begin()) {
|
||||
--it;
|
||||
if (it->type == Slic3r::CustomGCode::ColorChange)
|
||||
++shift;
|
||||
}
|
||||
return static_cast<int>(m_extruders_count) + shift;
|
||||
}
|
||||
};
|
||||
|
||||
static void convert_object_to_vertices(const Slic3r::PrintObject& object, const std::vector<std::string>& str_tool_colors,
|
||||
const std::vector<std::string>& str_color_print_colors, const std::vector<Slic3r::CustomGCode::Item>& color_print_values,
|
||||
size_t extruders_count, VerticesData& data)
|
||||
{
|
||||
const bool has_perimeters = object.is_step_done(Slic3r::posPerimeters);
|
||||
const bool has_infill = object.is_step_done(Slic3r::posInfill);
|
||||
const bool has_support = object.is_step_done(Slic3r::posSupportMaterial);
|
||||
|
||||
// order layers by print_z
|
||||
std::vector<const Slic3r::Layer*> layers;
|
||||
if (has_perimeters || has_infill) {
|
||||
layers.reserve(layers.size() + object.layers().size());
|
||||
std::copy(object.layers().begin(), object.layers().end(), std::back_inserter(layers));
|
||||
}
|
||||
if (has_support) {
|
||||
layers.reserve(layers.size() + object.support_layers().size());
|
||||
std::copy(object.support_layers().begin(), object.support_layers().end(), std::back_inserter(layers));
|
||||
}
|
||||
std::sort(layers.begin(), layers.end(), [](const Slic3r::Layer* l1, const Slic3r::Layer* l2) { return l1->print_z < l2->print_z; });
|
||||
|
||||
ObjectHelper object_helper(color_print_values, str_tool_colors.size(), str_color_print_colors.size(), extruders_count);
|
||||
|
||||
data.layers_zs.reserve(layers.size());
|
||||
for (const Slic3r::Layer* layer : layers) {
|
||||
data.layers_zs.emplace_back(static_cast<float>(layer->print_z));
|
||||
}
|
||||
|
||||
Slic3r::sort_remove_duplicates(data.layers_zs);
|
||||
|
||||
for (const Slic3r::Layer* layer : layers) {
|
||||
const size_t old_vertices_count = data.vertices.size();
|
||||
const float layer_z = static_cast<float>(layer->print_z);
|
||||
const auto it = std::find(data.layers_zs.begin(), data.layers_zs.end(), layer_z);
|
||||
assert(it != data.layers_zs.end());
|
||||
const size_t layer_id = (it != data.layers_zs.end()) ? std::distance(data.layers_zs.begin(), it) : 0;
|
||||
for (const Slic3r::PrintInstance& instance : object.instances()) {
|
||||
const Slic3r::Point& copy = instance.shift;
|
||||
for (const Slic3r::LayerRegion* layerm : layer->regions()) {
|
||||
if (layerm->slices.empty())
|
||||
continue;
|
||||
const Slic3r::PrintRegionConfig& cfg = layerm->region().config();
|
||||
if (has_perimeters) {
|
||||
const size_t extruder_id = static_cast<size_t>(std::max(cfg.wall_filament.value - 1, 0));
|
||||
convert_to_vertices(layerm->perimeters, layer_z, layer_id, extruder_id,
|
||||
object_helper.color_id(layer_z, extruder_id), EGCodeExtrusionRole::ExternalPerimeter,
|
||||
copy, data.vertices);
|
||||
}
|
||||
if (has_infill) {
|
||||
for (const Slic3r::ExtrusionEntity* ee : layerm->fills) {
|
||||
// fill represents infill extrusions of a single island.
|
||||
const auto& fill = *dynamic_cast<const Slic3r::ExtrusionEntityCollection*>(ee);
|
||||
if (!fill.entities.empty()) {
|
||||
const bool is_solid_infill = Slic3r::is_solid_infill(fill.entities.front()->role());
|
||||
const size_t extruder_id = is_solid_infill ?
|
||||
static_cast<size_t>(std::max(cfg.solid_infill_filament.value - 1, 0)) :
|
||||
static_cast<size_t>(std::max(cfg.sparse_infill_filament.value - 1, 0));
|
||||
convert_to_vertices(fill, layer_z, layer_id, extruder_id,
|
||||
object_helper.color_id(layer_z, extruder_id),
|
||||
is_solid_infill ? EGCodeExtrusionRole::SolidInfill : EGCodeExtrusionRole::InternalInfill,
|
||||
copy, data.vertices);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (has_support) {
|
||||
const Slic3r::SupportLayer* support_layer = dynamic_cast<const Slic3r::SupportLayer*>(layer);
|
||||
if (support_layer == nullptr)
|
||||
continue;
|
||||
const Slic3r::PrintObjectConfig& cfg = support_layer->object()->config();
|
||||
for (const Slic3r::ExtrusionEntity* extrusion_entity : support_layer->support_fills.entities) {
|
||||
const bool is_support_material = extrusion_entity->role() == Slic3r::ExtrusionRole::erSupportMaterial;
|
||||
const size_t extruder_id = is_support_material ?
|
||||
static_cast<size_t>(std::max(cfg.support_filament.value - 1, 0)) :
|
||||
static_cast<size_t>(std::max(cfg.support_interface_filament.value - 1, 0));
|
||||
convert_to_vertices(*extrusion_entity, layer_z, layer_id,
|
||||
extruder_id, object_helper.color_id(layer_z, extruder_id),
|
||||
is_support_material ? EGCodeExtrusionRole::SupportMaterial : EGCodeExtrusionRole::SupportMaterialInterface,
|
||||
copy, data.vertices);
|
||||
}
|
||||
}
|
||||
}
|
||||
// filter out empty layers
|
||||
const size_t new_vertices_count = data.vertices.size();
|
||||
if (new_vertices_count == old_vertices_count)
|
||||
data.layers_zs.erase(data.layers_zs.begin() + layer_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void convert_objects_to_vertices(const Slic3r::ConstPrintObjectPtrsAdaptor& objects, const std::vector<std::string>& str_tool_colors,
|
||||
const std::vector<std::string>& str_color_print_colors, const std::vector<Slic3r::CustomGCode::Item>& color_print_values, size_t extruders_count,
|
||||
std::vector<VerticesData>& data)
|
||||
{
|
||||
// extract vertices and layers zs object by object
|
||||
data.reserve(data.size() + objects.size());
|
||||
for (size_t i = 0; i < objects.size(); ++i) {
|
||||
data.emplace_back(VerticesData());
|
||||
convert_object_to_vertices(*objects[i], str_tool_colors, str_color_print_colors, color_print_values, extruders_count, data.back());
|
||||
}
|
||||
}
|
||||
|
||||
// mapping from Slic3r::Print to libvgcode::GCodeInputData
|
||||
GCodeInputData convert(const Slic3r::Print& print, const std::vector<std::string>& str_tool_colors,
|
||||
const std::vector<std::string>& str_color_print_colors, const std::vector<Slic3r::CustomGCode::Item>& color_print_values,
|
||||
size_t extruders_count)
|
||||
{
|
||||
GCodeInputData ret;
|
||||
std::vector<VerticesData> data;
|
||||
if (print.is_step_done(Slic3r::psSkirtBrim) && (print.has_skirt() || print.has_brim()))
|
||||
// extract vertices and layers zs from skirt/brim
|
||||
convert_brim_skirt_to_vertices(print, data);
|
||||
if (!print.wipe_tower_data().tool_changes.empty() && print.is_step_done(Slic3r::psWipeTower))
|
||||
// extract vertices and layers zs from wipe tower
|
||||
convert_wipe_tower_to_vertices(print, str_tool_colors, data);
|
||||
// extract vertices and layers zs from objects
|
||||
convert_objects_to_vertices(print.objects(), str_tool_colors, str_color_print_colors, color_print_values, extruders_count, data);
|
||||
|
||||
// collect layers zs
|
||||
std::vector<float> layers;
|
||||
for (const VerticesData& d : data) {
|
||||
layers.reserve(layers.size() + d.layers_zs.size());
|
||||
std::copy(d.layers_zs.begin(), d.layers_zs.end(), std::back_inserter(layers));
|
||||
}
|
||||
Slic3r::sort_remove_duplicates(layers);
|
||||
|
||||
// Now we need to copy the vertices into ret.vertices to be consumed by the preliminary G-code preview.
|
||||
// We need to collect vertices in the first layer for all objects, push them into the output vector
|
||||
// and then do the same for all the layers. The algorithm relies on the fact that the vertices from
|
||||
// lower layers are always placed after vertices from the higher layer.
|
||||
std::vector<size_t> vert_indices(data.size(), 0);
|
||||
for (size_t layer_id = 0; layer_id < layers.size(); ++layer_id) {
|
||||
const float layer_z = layers[layer_id];
|
||||
for (size_t obj_idx = 0; obj_idx < data.size(); ++obj_idx) {
|
||||
// d contains PathVertices for one object. Let's stuff everything below this layer_z into ret.vertices.
|
||||
const size_t start_idx = vert_indices[obj_idx];
|
||||
size_t idx = start_idx;
|
||||
while (idx < data[obj_idx].vertices.size() && data[obj_idx].vertices[idx].position[2] <= layer_z)
|
||||
++idx;
|
||||
// We have found a vertex above current layer_z. Let's copy the vertices into the output
|
||||
// and remember where to start when we process another layer.
|
||||
ret.vertices.insert(ret.vertices.end(),
|
||||
data[obj_idx].vertices.begin() + start_idx,
|
||||
data[obj_idx].vertices.begin() + idx);
|
||||
vert_indices[obj_idx] = idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// collect tool colors
|
||||
ret.tools_colors.reserve(str_tool_colors.size());
|
||||
for (const std::string& color : str_tool_colors) {
|
||||
ret.tools_colors.emplace_back(convert(color));
|
||||
}
|
||||
|
||||
// collect color print colors
|
||||
const std::vector<std::string>& str_colors = str_color_print_colors.empty() ? str_tool_colors : str_color_print_colors;
|
||||
ret.color_print_colors.reserve(str_colors.size());
|
||||
for (const std::string& color : str_colors) {
|
||||
ret.color_print_colors.emplace_back(convert(color));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace libvgcode
|
||||
|
||||
Reference in New Issue
Block a user