Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_world_coordinates
This commit is contained in:
commit
95c20f7f72
24 changed files with 463 additions and 193 deletions
|
@ -1,6 +1,6 @@
|
|||
#version 110
|
||||
|
||||
const vec3 back_color_dark = vec3(0.235, 0.235, 0.235);
|
||||
const vec3 back_color_dark = vec3(0.235, 0.235, 0.235);
|
||||
const vec3 back_color_light = vec3(0.365, 0.365, 0.365);
|
||||
|
||||
uniform sampler2D texture;
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
#version 110
|
||||
|
||||
attribute vec3 v_position;
|
||||
attribute vec2 v_tex_coords;
|
||||
|
||||
varying vec2 tex_coords;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_ModelViewProjectionMatrix * vec4(v_position.x, v_position.y, v_position.z, 1.0);
|
||||
// the following line leads to crash on some Intel graphics card
|
||||
//gl_Position = gl_ModelViewProjectionMatrix * vec4(v_position, 1.0);
|
||||
tex_coords = v_tex_coords;
|
||||
gl_Position = ftransform();
|
||||
tex_coords = gl_MultiTexCoord0.xy;
|
||||
}
|
||||
|
|
|
@ -836,6 +836,7 @@ extern "C" {
|
|||
"leak:libnvidia-glcore.so\n" // For NVidia driver.
|
||||
"leak:libnvidia-tls.so\n" // For NVidia driver.
|
||||
"leak:terminator_CreateDevice\n" // For Intel Vulkan drivers.
|
||||
"leak:swrast_dri.so\n" // For Mesa 3D software driver.
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "Extruder.hpp"
|
||||
#include "GCodeWriter.hpp"
|
||||
#include "PrintConfig.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
@ -7,24 +8,24 @@ Extruder::Extruder(unsigned int id, GCodeConfig *config) :
|
|||
m_id(id),
|
||||
m_config(config)
|
||||
{
|
||||
reset();
|
||||
|
||||
// cache values that are going to be called often
|
||||
m_e_per_mm3 = this->extrusion_multiplier();
|
||||
if (! m_config->use_volumetric_e)
|
||||
m_e_per_mm3 /= this->filament_crossection();
|
||||
}
|
||||
|
||||
double Extruder::extrude(double dE)
|
||||
std::pair<double, double> Extruder::extrude(double dE)
|
||||
{
|
||||
// in case of relative E distances we always reset to 0 before any output
|
||||
if (m_config->use_relative_e_distances)
|
||||
m_E = 0.;
|
||||
// Quantize extruder delta to G-code resolution.
|
||||
dE = GCodeFormatter::quantize_e(dE);
|
||||
m_E += dE;
|
||||
m_absolute_E += dE;
|
||||
if (dE < 0.)
|
||||
m_retracted -= dE;
|
||||
return dE;
|
||||
return std::make_pair(dE, m_E);
|
||||
}
|
||||
|
||||
/* This method makes sure the extruder is retracted by the specified amount
|
||||
|
@ -34,28 +35,33 @@ double Extruder::extrude(double dE)
|
|||
The restart_extra argument sets the extra length to be used for
|
||||
unretraction. If we're actually performing a retraction, any restart_extra
|
||||
value supplied will overwrite the previous one if any. */
|
||||
double Extruder::retract(double length, double restart_extra)
|
||||
std::pair<double, double> Extruder::retract(double retract_length, double restart_extra)
|
||||
{
|
||||
// in case of relative E distances we always reset to 0 before any output
|
||||
if (m_config->use_relative_e_distances)
|
||||
m_E = 0.;
|
||||
double to_retract = std::max(0., length - m_retracted);
|
||||
// Quantize extruder delta to G-code resolution.
|
||||
double to_retract = this->retract_to_go(retract_length);
|
||||
if (to_retract > 0.) {
|
||||
m_E -= to_retract;
|
||||
m_absolute_E -= to_retract;
|
||||
m_retracted += to_retract;
|
||||
m_restart_extra = restart_extra;
|
||||
m_restart_extra = restart_extra;
|
||||
}
|
||||
return to_retract;
|
||||
return std::make_pair(to_retract, m_E);
|
||||
}
|
||||
|
||||
double Extruder::unretract()
|
||||
double Extruder::retract_to_go(double retract_length) const
|
||||
{
|
||||
double dE = m_retracted + m_restart_extra;
|
||||
this->extrude(dE);
|
||||
return std::max(0., GCodeFormatter::quantize_e(retract_length - m_retracted));
|
||||
}
|
||||
|
||||
std::pair<double, double> Extruder::unretract()
|
||||
{
|
||||
auto [dE, emitE] = this->extrude(m_retracted + m_restart_extra);
|
||||
m_retracted = 0.;
|
||||
m_restart_extra = 0.;
|
||||
return dE;
|
||||
return std::make_pair(dE, emitE);
|
||||
}
|
||||
|
||||
// Used filament volume in mm^3.
|
||||
|
|
|
@ -12,22 +12,24 @@ class Extruder
|
|||
{
|
||||
public:
|
||||
Extruder(unsigned int id, GCodeConfig *config);
|
||||
virtual ~Extruder() {}
|
||||
|
||||
void reset() {
|
||||
m_E = 0;
|
||||
m_absolute_E = 0;
|
||||
m_retracted = 0;
|
||||
m_restart_extra = 0;
|
||||
}
|
||||
~Extruder() = default;
|
||||
|
||||
unsigned int id() const { return m_id; }
|
||||
|
||||
double extrude(double dE);
|
||||
double retract(double length, double restart_extra);
|
||||
double unretract();
|
||||
double E() const { return m_E; }
|
||||
void reset_E() { m_E = 0.; }
|
||||
// Following three methods emit:
|
||||
// first - extrusion delta
|
||||
// second - number to emit to G-code: This may be delta for relative mode or a distance from last reset_E() for absolute mode.
|
||||
// They also quantize the E axis to G-code resolution.
|
||||
std::pair<double, double> extrude(double dE);
|
||||
std::pair<double, double> retract(double retract_length, double restart_extra);
|
||||
std::pair<double, double> unretract();
|
||||
// How much to retract yet before retract_length is reached?
|
||||
// The value is quantized to G-code resolution.
|
||||
double retract_to_go(double retract_length) const;
|
||||
|
||||
// Reset the current state of the E axis (this is only needed for relative extruder addressing mode anyways).
|
||||
// Returns true if the extruder was non-zero before reset.
|
||||
bool reset_E() { bool modified = m_E != 0; m_E = 0.; return modified; }
|
||||
double e_per_mm(double mm3_per_mm) const { return mm3_per_mm * m_e_per_mm3; }
|
||||
double e_per_mm3() const { return m_e_per_mm3; }
|
||||
// Used filament volume in mm^3.
|
||||
|
@ -57,14 +59,16 @@ private:
|
|||
GCodeConfig *m_config;
|
||||
// Print-wide global ID of this extruder.
|
||||
unsigned int m_id;
|
||||
// Current state of the extruder axis, may be resetted if use_relative_e_distances.
|
||||
double m_E;
|
||||
// Current state of the extruder axis.
|
||||
// For absolute extruder addressing, it is the current state since the last reset (G92 E0) issued at the end of the last retraction.
|
||||
// For relative extruder addressing, it is the E axis difference emitted into the G-code the last time.
|
||||
double m_E { 0 };
|
||||
// Current state of the extruder tachometer, used to output the extruded_volume() and used_filament() statistics.
|
||||
double m_absolute_E;
|
||||
double m_absolute_E { 0 };
|
||||
// Current positive amount of retraction.
|
||||
double m_retracted;
|
||||
double m_retracted { 0 };
|
||||
// When retracted, this value stores the extra amount of priming on deretraction.
|
||||
double m_restart_extra;
|
||||
double m_restart_extra { 0 };
|
||||
double m_e_per_mm3;
|
||||
};
|
||||
|
||||
|
@ -76,4 +80,4 @@ inline bool operator> (const Extruder &e1, const Extruder &e2) { return e1.id()
|
|||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // slic3r_Extruder_hpp_
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <boost/foreach.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/beast/core/detail/base64.hpp>
|
||||
|
||||
#include <boost/nowide/iostream.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
|
@ -155,63 +154,52 @@ namespace Slic3r {
|
|||
|
||||
std::string Wipe::wipe(GCode& gcodegen, bool toolchange)
|
||||
{
|
||||
std::string gcode;
|
||||
std::string gcode;
|
||||
const Extruder &extruder = *gcodegen.writer().extruder();
|
||||
|
||||
/* Reduce feedrate a bit; travel speed is often too high to move on existing material.
|
||||
Too fast = ripping of existing material; too slow = short wipe path, thus more blob. */
|
||||
double wipe_speed = gcodegen.writer().config.travel_speed.value * 0.8;
|
||||
|
||||
// get the retraction length
|
||||
double length = toolchange
|
||||
? gcodegen.writer().extruder()->retract_length_toolchange()
|
||||
: gcodegen.writer().extruder()->retract_length();
|
||||
// Shorten the retraction length by the amount already retracted before wipe.
|
||||
length *= (1. - gcodegen.writer().extruder()->retract_before_wipe());
|
||||
|
||||
if (length > 0) {
|
||||
/* Calculate how long we need to travel in order to consume the required
|
||||
amount of retraction. In other words, how far do we move in XY at wipe_speed
|
||||
for the time needed to consume retract_length at retract_speed? */
|
||||
double wipe_dist = scale_(length / gcodegen.writer().extruder()->retract_speed() * wipe_speed);
|
||||
|
||||
/* Take the stored wipe path and replace first point with the current actual position
|
||||
(they might be different, for example, in case of loop clipping). */
|
||||
Polyline wipe_path;
|
||||
wipe_path.append(gcodegen.last_pos());
|
||||
wipe_path.append(
|
||||
this->path.points.begin() + 1,
|
||||
this->path.points.end()
|
||||
);
|
||||
|
||||
wipe_path.clip_end(wipe_path.length() - wipe_dist);
|
||||
|
||||
// subdivide the retraction in segments
|
||||
if (!wipe_path.empty()) {
|
||||
// add tag for processor
|
||||
// Remaining quantized retraction length.
|
||||
if (double retract_length = extruder.retract_to_go(toolchange ? extruder.retract_length_toolchange() : extruder.retract_length());
|
||||
retract_length > 0 && this->path.size() >= 2) {
|
||||
// Reduce feedrate a bit; travel speed is often too high to move on existing material.
|
||||
// Too fast = ripping of existing material; too slow = short wipe path, thus more blob.
|
||||
const double wipe_speed = gcodegen.writer().config.travel_speed.value * 0.8;
|
||||
// Reduce retraction length a bit to avoid effective retraction speed to be greater than the configured one
|
||||
// due to rounding (TODO: test and/or better math for this).
|
||||
const double xy_to_e = 0.95 * extruder.retract_speed() / wipe_speed;
|
||||
// Start with the current position, which may be different from the wipe path start in case of loop clipping.
|
||||
Vec2d prev = gcodegen.point_to_gcode_quantized(gcodegen.last_pos());
|
||||
auto it = this->path.points.begin();
|
||||
Vec2d p = gcodegen.point_to_gcode_quantized(*(++ it));
|
||||
if (p != prev) {
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_Start) + "\n";
|
||||
for (const Line& line : wipe_path.lines()) {
|
||||
double segment_length = line.length();
|
||||
/* Reduce retraction length a bit to avoid effective retraction speed to be greater than the configured one
|
||||
due to rounding (TODO: test and/or better math for this) */
|
||||
double dE = length * (segment_length / wipe_dist) * 0.95;
|
||||
auto end = this->path.points.end();
|
||||
bool done = false;
|
||||
for (; it != end; ++ it) {
|
||||
p = gcodegen.point_to_gcode_quantized(*it);
|
||||
double segment_length = (p - prev).norm();
|
||||
double dE = GCodeFormatter::quantize_e(xy_to_e * segment_length);
|
||||
if (dE > retract_length - EPSILON) {
|
||||
if (dE > retract_length + EPSILON)
|
||||
// Shorten the segment.
|
||||
p = prev + (p - prev) * (retract_length / dE);
|
||||
dE = retract_length;
|
||||
done = true;
|
||||
}
|
||||
//FIXME one shall not generate the unnecessary G1 Fxxx commands, here wipe_speed is a constant inside this cycle.
|
||||
// Is it here for the cooling markers? Or should it be outside of the cycle?
|
||||
gcode += gcodegen.writer().set_speed(wipe_speed * 60, "", gcodegen.enable_cooling_markers() ? ";_WIPE" : "");
|
||||
gcode += gcodegen.writer().extrude_to_xy(
|
||||
gcodegen.point_to_gcode(line.b),
|
||||
-dE,
|
||||
"wipe and retract"
|
||||
);
|
||||
gcode += gcodegen.writer().set_speed(wipe_speed * 60, {}, gcodegen.enable_cooling_markers() ? ";_WIPE" : "");
|
||||
gcode += gcodegen.writer().extrude_to_xy(p, -dE, "wipe and retract");
|
||||
prev = p;
|
||||
retract_length -= dE;
|
||||
}
|
||||
// add tag for processor
|
||||
gcode += ";" + GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Wipe_End) + "\n";
|
||||
gcodegen.set_last_pos(wipe_path.points.back());
|
||||
gcodegen.set_last_pos(gcodegen.gcode_to_point(prev));
|
||||
}
|
||||
|
||||
// prevent wiping again on same path
|
||||
this->reset_path();
|
||||
}
|
||||
|
||||
// Prevent wiping again on the same path.
|
||||
this->reset_path();
|
||||
return gcode;
|
||||
}
|
||||
|
||||
|
@ -1119,11 +1107,16 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
// Write information on the generator.
|
||||
file.write_format("; %s\n\n", Slic3r::header_slic3r_generated().c_str());
|
||||
|
||||
GCodeThumbnails::export_thumbnails_to_file(thumbnail_cb,
|
||||
print.full_print_config().option<ConfigOptionPoints>("thumbnails")->values,
|
||||
print.full_print_config().opt_enum<GCodeThumbnailsFormat>("thumbnails_format"),
|
||||
[&file](const char* sz) { file.write(sz); },
|
||||
[&print]() { print.throw_if_canceled(); });
|
||||
// Unit tests or command line slicing may not define "thumbnails" or "thumbnails_format".
|
||||
// If "thumbnails_format" is not defined, export to PNG.
|
||||
if (const auto [thumbnails, thumbnails_format] = std::make_pair(
|
||||
print.full_print_config().option<ConfigOptionPoints>("thumbnails"),
|
||||
print.full_print_config().option<ConfigOptionEnum<GCodeThumbnailsFormat>>("thumbnails_format"));
|
||||
thumbnails)
|
||||
GCodeThumbnails::export_thumbnails_to_file(
|
||||
thumbnail_cb, thumbnails->values, thumbnails_format ? thumbnails_format->value : GCodeThumbnailsFormat::PNG,
|
||||
[&file](const char* sz) { file.write(sz); },
|
||||
[&print]() { print.throw_if_canceled(); });
|
||||
|
||||
// Write notes (content of the Print Settings tab -> Notes)
|
||||
{
|
||||
|
@ -3005,13 +2998,15 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
|||
double path_length = 0.;
|
||||
{
|
||||
std::string comment = m_config.gcode_comments ? description : "";
|
||||
for (const Line &line : path.polyline.lines()) {
|
||||
const double line_length = line.length() * SCALING_FACTOR;
|
||||
Vec2d prev = this->point_to_gcode_quantized(path.polyline.points.front());
|
||||
auto it = path.polyline.points.begin();
|
||||
auto end = path.polyline.points.end();
|
||||
for (++ it; it != end; ++ it) {
|
||||
Vec2d p = this->point_to_gcode_quantized(*it);
|
||||
const double line_length = (p - prev).norm();
|
||||
path_length += line_length;
|
||||
gcode += m_writer.extrude_to_xy(
|
||||
this->point_to_gcode(line.b),
|
||||
e_per_mm * line_length,
|
||||
comment);
|
||||
gcode += m_writer.extrude_to_xy(p, e_per_mm * line_length, comment);
|
||||
prev = p;
|
||||
}
|
||||
}
|
||||
if (m_enable_cooling_markers)
|
||||
|
@ -3234,7 +3229,13 @@ std::string GCode::set_extruder(unsigned int extruder_id, double print_z)
|
|||
Vec2d GCode::point_to_gcode(const Point &point) const
|
||||
{
|
||||
Vec2d extruder_offset = EXTRUDER_CONFIG(extruder_offset);
|
||||
return unscale(point) + m_origin - extruder_offset;
|
||||
return unscaled<double>(point) + m_origin - extruder_offset;
|
||||
}
|
||||
|
||||
Vec2d GCode::point_to_gcode_quantized(const Point &point) const
|
||||
{
|
||||
Vec2d p = this->point_to_gcode(point);
|
||||
return { GCodeFormatter::quantize_xyzf(p.x()), GCodeFormatter::quantize_xyzf(p.y()) };
|
||||
}
|
||||
|
||||
// convert a model-space scaled point into G-code coordinates
|
||||
|
|
|
@ -55,9 +55,9 @@ public:
|
|||
Polyline path;
|
||||
|
||||
Wipe() : enable(false) {}
|
||||
bool has_path() const { return !this->path.points.empty(); }
|
||||
void reset_path() { this->path = Polyline(); }
|
||||
std::string wipe(GCode &gcodegen, bool toolchange = false);
|
||||
bool has_path() const { return ! this->path.empty(); }
|
||||
void reset_path() { this->path.clear(); }
|
||||
std::string wipe(GCode &gcodegen, bool toolchange);
|
||||
};
|
||||
|
||||
class WipeTowerIntegration {
|
||||
|
@ -151,7 +151,10 @@ public:
|
|||
void set_origin(const Vec2d &pointf);
|
||||
void set_origin(const coordf_t x, const coordf_t y) { this->set_origin(Vec2d(x, y)); }
|
||||
const Point& last_pos() const { return m_last_pos; }
|
||||
// Convert coordinates of the active object to G-code coordinates, possibly adjusted for extruder offset.
|
||||
Vec2d point_to_gcode(const Point &point) const;
|
||||
// Convert coordinates of the active object to G-code coordinates, possibly adjusted for extruder offset and quantized to G-code resolution.
|
||||
Vec2d point_to_gcode_quantized(const Point &point) const;
|
||||
Point gcode_to_point(const Vec2d &point) const;
|
||||
const FullPrintConfig &config() const { return m_config; }
|
||||
const Layer* layer() const { return m_layer; }
|
||||
|
|
|
@ -1955,7 +1955,7 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers
|
|||
if (!m_result.spiral_vase_layers.empty() && m_end_position[Z] == m_result.spiral_vase_layers.back().first)
|
||||
m_result.spiral_vase_layers.back().second.second = move_id;
|
||||
else
|
||||
m_result.spiral_vase_layers.push_back({ m_end_position[Z], { move_id, move_id } });
|
||||
m_result.spiral_vase_layers.push_back({ static_cast<float>(m_end_position[Z]), { move_id, move_id } });
|
||||
}
|
||||
#endif // ENABLE_SPIRAL_VASE_LAYERS
|
||||
return;
|
||||
|
@ -2505,7 +2505,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||
AxisCoords delta_pos;
|
||||
for (unsigned char a = X; a <= E; ++a) {
|
||||
delta_pos[a] = m_end_position[a] - m_start_position[a];
|
||||
max_abs_delta = std::max(max_abs_delta, std::abs(delta_pos[a]));
|
||||
max_abs_delta = std::max<float>(max_abs_delta, std::abs(delta_pos[a]));
|
||||
}
|
||||
|
||||
// no displacement, return
|
||||
|
@ -2615,7 +2615,7 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||
if (curr.abs_axis_feedrate[a] != 0.0f) {
|
||||
float axis_max_feedrate = get_axis_max_feedrate(static_cast<PrintEstimatedStatistics::ETimeMode>(i), static_cast<Axis>(a));
|
||||
if (axis_max_feedrate != 0.0f)
|
||||
min_feedrate_factor = std::min(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]);
|
||||
min_feedrate_factor = std::min<float>(min_feedrate_factor, axis_max_feedrate / curr.abs_axis_feedrate[a]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3279,7 +3279,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type)
|
|||
#else
|
||||
Vec3f(m_end_position[X], m_end_position[Y], m_processing_start_custom_gcode ? m_first_layer_height : m_end_position[Z]) + m_extruder_offsets[m_extruder_id],
|
||||
#endif // ENABLE_Z_OFFSET_CORRECTION
|
||||
m_end_position[E] - m_start_position[E],
|
||||
static_cast<float>(m_end_position[E] - m_start_position[E]),
|
||||
m_feedrate,
|
||||
m_width,
|
||||
m_height,
|
||||
|
|
|
@ -178,7 +178,7 @@ namespace Slic3r {
|
|||
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
|
||||
private:
|
||||
using AxisCoords = std::array<float, 4>;
|
||||
using AxisCoords = std::array<double, 4>;
|
||||
using ExtruderColors = std::vector<unsigned char>;
|
||||
using ExtruderTemps = std::vector<float>;
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ static double calc_max_layer_height(const PrintConfig &config, double max_object
|
|||
{
|
||||
double max_layer_height = std::numeric_limits<double>::max();
|
||||
for (size_t i = 0; i < config.nozzle_diameter.values.size(); ++ i) {
|
||||
double mlh = config.max_layer_height.values[i];
|
||||
double mlh = config.max_layer_height.get_at(i);
|
||||
if (mlh == 0.)
|
||||
mlh = 0.75 * config.nozzle_diameter.values[i];
|
||||
max_layer_height = std::min(max_layer_height, mlh);
|
||||
|
|
|
@ -79,7 +79,7 @@ std::string GCodeWriter::postamble() const
|
|||
std::string GCodeWriter::set_temperature(unsigned int temperature, bool wait, int tool) const
|
||||
{
|
||||
if (wait && (FLAVOR_IS(gcfMakerWare) || FLAVOR_IS(gcfSailfish)))
|
||||
return "";
|
||||
return {};
|
||||
|
||||
std::string code, comment;
|
||||
if (wait && FLAVOR_IS_NOT(gcfTeacup) && FLAVOR_IS_NOT(gcfRepRapFirmware)) {
|
||||
|
@ -192,32 +192,18 @@ std::string GCodeWriter::set_acceleration(unsigned int acceleration)
|
|||
|
||||
std::string GCodeWriter::reset_e(bool force)
|
||||
{
|
||||
if (FLAVOR_IS(gcfMach3)
|
||||
|| FLAVOR_IS(gcfMakerWare)
|
||||
|| FLAVOR_IS(gcfSailfish))
|
||||
return "";
|
||||
|
||||
if (m_extruder != nullptr) {
|
||||
if (m_extruder->E() == 0. && ! force)
|
||||
return "";
|
||||
m_extruder->reset_E();
|
||||
}
|
||||
|
||||
if (! m_extrusion_axis.empty() && ! this->config.use_relative_e_distances) {
|
||||
std::ostringstream gcode;
|
||||
gcode << "G92 " << m_extrusion_axis << "0";
|
||||
if (this->config.gcode_comments) gcode << " ; reset extrusion distance";
|
||||
gcode << "\n";
|
||||
return gcode.str();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
return
|
||||
FLAVOR_IS(gcfMach3) || FLAVOR_IS(gcfMakerWare) || FLAVOR_IS(gcfSailfish) || this->config.use_relative_e_distances ||
|
||||
(m_extruder != nullptr && ! m_extruder->reset_E() && ! force) ||
|
||||
m_extrusion_axis.empty() ?
|
||||
std::string{} :
|
||||
std::string("G92 ") + m_extrusion_axis + (this->config.gcode_comments ? "0 ; reset extrusion distance\n" : "0\n");
|
||||
}
|
||||
|
||||
std::string GCodeWriter::update_progress(unsigned int num, unsigned int tot, bool allow_100) const
|
||||
{
|
||||
if (FLAVOR_IS_NOT(gcfMakerWare) && FLAVOR_IS_NOT(gcfSailfish))
|
||||
return "";
|
||||
return {};
|
||||
|
||||
unsigned int percent = (unsigned int)floor(100.0 * num / tot + 0.5);
|
||||
if (!allow_100) percent = std::min(percent, (unsigned int)99);
|
||||
|
@ -269,8 +255,8 @@ std::string GCodeWriter::set_speed(double F, const std::string &comment, const s
|
|||
|
||||
std::string GCodeWriter::travel_to_xy(const Vec2d &point, const std::string &comment)
|
||||
{
|
||||
m_pos(0) = point(0);
|
||||
m_pos(1) = point(1);
|
||||
m_pos.x() = point.x();
|
||||
m_pos.y() = point.y();
|
||||
|
||||
GCodeG1Formatter w;
|
||||
w.emit_xy(point);
|
||||
|
@ -290,9 +276,9 @@ std::string GCodeWriter::travel_to_xyz(const Vec3d &point, const std::string &co
|
|||
don't perform the Z move but we only move in the XY plane and
|
||||
adjust the nominal Z by reducing the lift amount that will be
|
||||
used for unlift. */
|
||||
if (!this->will_move_z(point(2))) {
|
||||
double nominal_z = m_pos(2) - m_lifted;
|
||||
m_lifted -= (point(2) - nominal_z);
|
||||
if (!this->will_move_z(point.z())) {
|
||||
double nominal_z = m_pos.z() - m_lifted;
|
||||
m_lifted -= (point.z() - nominal_z);
|
||||
// In case that retract_lift == layer_height we could end up with almost zero in_m_lifted
|
||||
// and a retract could be skipped (https://github.com/prusa3d/PrusaSlicer/issues/2154
|
||||
if (std::abs(m_lifted) < EPSILON)
|
||||
|
@ -318,11 +304,11 @@ std::string GCodeWriter::travel_to_z(double z, const std::string &comment)
|
|||
we don't perform the move but we only adjust the nominal Z by
|
||||
reducing the lift amount that will be used for unlift. */
|
||||
if (!this->will_move_z(z)) {
|
||||
double nominal_z = m_pos(2) - m_lifted;
|
||||
double nominal_z = m_pos.z() - m_lifted;
|
||||
m_lifted -= (z - nominal_z);
|
||||
if (std::abs(m_lifted) < EPSILON)
|
||||
m_lifted = 0.;
|
||||
return "";
|
||||
return {};
|
||||
}
|
||||
|
||||
/* In all the other cases, we perform an actual Z move and cancel
|
||||
|
@ -333,7 +319,7 @@ std::string GCodeWriter::travel_to_z(double z, const std::string &comment)
|
|||
|
||||
std::string GCodeWriter::_travel_to_z(double z, const std::string &comment)
|
||||
{
|
||||
m_pos(2) = z;
|
||||
m_pos.z() = z;
|
||||
|
||||
double speed = this->config.travel_speed_z.value;
|
||||
if (speed == 0.)
|
||||
|
@ -351,8 +337,8 @@ bool GCodeWriter::will_move_z(double z) const
|
|||
/* If target Z is lower than current Z but higher than nominal Z
|
||||
we don't perform an actual Z move. */
|
||||
if (m_lifted > 0) {
|
||||
double nominal_z = m_pos(2) - m_lifted;
|
||||
if (z >= nominal_z && z <= m_pos(2))
|
||||
double nominal_z = m_pos.z() - m_lifted;
|
||||
if (z >= nominal_z && z <= m_pos.z())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -360,17 +346,17 @@ bool GCodeWriter::will_move_z(double z) const
|
|||
|
||||
std::string GCodeWriter::extrude_to_xy(const Vec2d &point, double dE, const std::string &comment)
|
||||
{
|
||||
m_pos(0) = point(0);
|
||||
m_pos(1) = point(1);
|
||||
m_extruder->extrude(dE);
|
||||
m_pos.x() = point.x();
|
||||
m_pos.y() = point.y();
|
||||
|
||||
GCodeG1Formatter w;
|
||||
w.emit_xy(point);
|
||||
w.emit_e(m_extrusion_axis, m_extruder->E());
|
||||
w.emit_e(m_extrusion_axis, m_extruder->extrude(dE).second);
|
||||
w.emit_comment(this->config.gcode_comments, comment);
|
||||
return w.string();
|
||||
}
|
||||
|
||||
#if 0
|
||||
std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment)
|
||||
{
|
||||
m_pos = point;
|
||||
|
@ -383,6 +369,7 @@ std::string GCodeWriter::extrude_to_xyz(const Vec3d &point, double dE, const std
|
|||
w.emit_comment(this->config.gcode_comments, comment);
|
||||
return w.string();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::string GCodeWriter::retract(bool before_wipe)
|
||||
{
|
||||
|
@ -422,14 +409,13 @@ std::string GCodeWriter::_retract(double length, double restart_extra, const std
|
|||
restart_extra = restart_extra * area;
|
||||
}
|
||||
|
||||
|
||||
std::string gcode;
|
||||
if (double dE = m_extruder->retract(length, restart_extra); dE != 0) {
|
||||
if (auto [dE, emitE] = m_extruder->retract(length, restart_extra); dE != 0) {
|
||||
if (this->config.use_firmware_retraction) {
|
||||
gcode = FLAVOR_IS(gcfMachinekit) ? "G22 ; retract\n" : "G10 ; retract\n";
|
||||
} else if (! m_extrusion_axis.empty()) {
|
||||
GCodeG1Formatter w;
|
||||
w.emit_e(m_extrusion_axis, m_extruder->E());
|
||||
w.emit_e(m_extrusion_axis, emitE);
|
||||
w.emit_f(m_extruder->retract_speed() * 60.);
|
||||
w.emit_comment(this->config.gcode_comments, comment);
|
||||
gcode = w.string();
|
||||
|
@ -449,14 +435,14 @@ std::string GCodeWriter::unretract()
|
|||
if (FLAVOR_IS(gcfMakerWare))
|
||||
gcode = "M101 ; extruder on\n";
|
||||
|
||||
if (double dE = m_extruder->unretract(); dE != 0) {
|
||||
if (auto [dE, emitE] = m_extruder->unretract(); dE != 0) {
|
||||
if (this->config.use_firmware_retraction) {
|
||||
gcode += FLAVOR_IS(gcfMachinekit) ? "G23 ; unretract\n" : "G11 ; unretract\n";
|
||||
gcode += this->reset_e();
|
||||
} else if (! m_extrusion_axis.empty()) {
|
||||
// use G1 instead of G0 because G0 will blend the restart with the previous travel move
|
||||
GCodeG1Formatter w;
|
||||
w.emit_e(m_extrusion_axis, m_extruder->E());
|
||||
w.emit_e(m_extrusion_axis, emitE);
|
||||
w.emit_f(m_extruder->deretract_speed() * 60.);
|
||||
w.emit_comment(this->config.gcode_comments, " ; unretract");
|
||||
gcode += w.string();
|
||||
|
@ -476,21 +462,21 @@ std::string GCodeWriter::lift()
|
|||
{
|
||||
double above = this->config.retract_lift_above.get_at(m_extruder->id());
|
||||
double below = this->config.retract_lift_below.get_at(m_extruder->id());
|
||||
if (m_pos(2) >= above && (below == 0 || m_pos(2) <= below))
|
||||
if (m_pos.z() >= above && (below == 0 || m_pos.z() <= below))
|
||||
target_lift = this->config.retract_lift.get_at(m_extruder->id());
|
||||
}
|
||||
if (m_lifted == 0 && target_lift > 0) {
|
||||
m_lifted = target_lift;
|
||||
return this->_travel_to_z(m_pos(2) + target_lift, "lift Z");
|
||||
return this->_travel_to_z(m_pos.z() + target_lift, "lift Z");
|
||||
}
|
||||
return "";
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string GCodeWriter::unlift()
|
||||
{
|
||||
std::string gcode;
|
||||
if (m_lifted > 0) {
|
||||
gcode += this->_travel_to_z(m_pos(2) - m_lifted, "restore layer Z");
|
||||
gcode += this->_travel_to_z(m_pos.z() - m_lifted, "restore layer Z");
|
||||
m_lifted = 0;
|
||||
}
|
||||
return gcode;
|
||||
|
|
|
@ -61,7 +61,7 @@ public:
|
|||
std::string travel_to_z(double z, const std::string &comment = std::string());
|
||||
bool will_move_z(double z) const;
|
||||
std::string extrude_to_xy(const Vec2d &point, double dE, const std::string &comment = std::string());
|
||||
std::string extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment = std::string());
|
||||
// std::string extrude_to_xyz(const Vec3d &point, double dE, const std::string &comment = std::string());
|
||||
std::string retract(bool before_wipe = false);
|
||||
std::string retract_for_toolchange(bool before_wipe = false);
|
||||
std::string unretract();
|
||||
|
@ -121,6 +121,14 @@ public:
|
|||
// static constexpr const int E_EXPORT_DIGITS = 9;
|
||||
#endif
|
||||
|
||||
static constexpr const std::array<double, 10> pow_10 { 1., 10., 100., 1000., 10000., 100000., 1000000., 10000000., 100000000., 1000000000.};
|
||||
static constexpr const std::array<double, 10> pow_10_inv{1./1., 1./10., 1./100., 1./1000., 1./10000., 1./100000., 1./1000000., 1./10000000., 1./100000000., 1./1000000000.};
|
||||
|
||||
// Quantize doubles to a resolution of the G-code.
|
||||
static double quantize(double v, size_t ndigits) { return std::round(v * pow_10[ndigits]) * pow_10_inv[ndigits]; }
|
||||
static double quantize_xyzf(double v) { return quantize(v, XYZF_EXPORT_DIGITS); }
|
||||
static double quantize_e(double v) { return quantize(v, E_EXPORT_DIGITS); }
|
||||
|
||||
void emit_axis(const char axis, const double v, size_t digits);
|
||||
|
||||
void emit_xy(const Vec2d &point) {
|
||||
|
|
|
@ -346,10 +346,11 @@ private:
|
|||
friend class Print;
|
||||
|
||||
PrintObject(Print* print, ModelObject* model_object, const Transform3d& trafo, PrintInstances&& instances);
|
||||
~PrintObject() {
|
||||
~PrintObject() override {
|
||||
if (m_shared_regions && --m_shared_regions->m_ref_cnt == 0)
|
||||
delete m_shared_regions;
|
||||
clear_layers();
|
||||
clear_support_layers();
|
||||
}
|
||||
|
||||
void config_apply(const ConfigBase &other, bool ignore_nonexistent = false) { m_config.apply(other, ignore_nonexistent); }
|
||||
|
|
|
@ -3754,6 +3754,7 @@ void modulate_extrusion_by_overlapping_layers(
|
|||
assert(path != nullptr);
|
||||
polylines.emplace_back(Polyline(std::move(path->polyline)));
|
||||
path_ends.emplace_back(std::pair<Point, Point>(polylines.back().points.front(), polylines.back().points.back()));
|
||||
delete path;
|
||||
}
|
||||
}
|
||||
// Destroy the original extrusion paths, their polylines were moved to path_fragments already.
|
||||
|
|
|
@ -27,6 +27,7 @@ static const Slic3r::ColorRGBA DEFAULT_TRANSPARENT_GRID_COLOR = { 0.9f, 0.9f, 0
|
|||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
#if !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
bool GeometryBuffer::set_from_triangles(const std::vector<Vec2f> &triangles, float z)
|
||||
{
|
||||
if (triangles.empty()) {
|
||||
|
@ -95,6 +96,7 @@ const float* GeometryBuffer::get_vertices_data() const
|
|||
{
|
||||
return (m_vertices.size() > 0) ? (const float*)m_vertices.data() : nullptr;
|
||||
}
|
||||
#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
const float Bed3D::Axes::DefaultStemRadius = 0.5f;
|
||||
const float Bed3D::Axes::DefaultStemLength = 25.0f;
|
||||
|
@ -198,6 +200,13 @@ bool Bed3D::set_shape(const Pointfs& bed_shape, const double max_print_height, c
|
|||
m_model_filename = model_filename;
|
||||
m_extended_bounding_box = this->calc_extended_bounding_box();
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
m_contour = ExPolygon(Polygon::new_scale(bed_shape));
|
||||
m_polygon = offset(m_contour.contour, (float)m_contour.contour.bounding_box().radius() * 1.7f, jtRound, scale_(0.5)).front();
|
||||
|
||||
m_triangles.reset();
|
||||
m_gridlines.reset();
|
||||
#else
|
||||
ExPolygon poly{ Polygon::new_scale(bed_shape) };
|
||||
|
||||
calc_triangles(poly);
|
||||
|
@ -205,9 +214,10 @@ bool Bed3D::set_shape(const Pointfs& bed_shape, const double max_print_height, c
|
|||
const BoundingBox& bed_bbox = poly.contour.bounding_box();
|
||||
calc_gridlines(poly, bed_bbox);
|
||||
|
||||
m_polygon = offset(poly.contour, (float)bed_bbox.radius() * 1.7f, jtRound, scale_(0.5))[0];
|
||||
m_polygon = offset(poly.contour, (float)bed_bbox.radius() * 1.7f, jtRound, scale_(0.5)).front();
|
||||
|
||||
this->release_VBOs();
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
m_texture.reset();
|
||||
m_model.reset();
|
||||
|
||||
|
@ -288,6 +298,104 @@ BoundingBoxf3 Bed3D::calc_extended_bounding_box() const
|
|||
return out;
|
||||
}
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
void Bed3D::init_triangles()
|
||||
{
|
||||
if (m_triangles.is_initialized())
|
||||
return;
|
||||
|
||||
if (m_contour.empty())
|
||||
return;
|
||||
|
||||
const std::vector<Vec2f> triangles = triangulate_expolygon_2f(m_contour, NORMALS_UP);
|
||||
if (triangles.empty() || triangles.size() % 3 != 0)
|
||||
return;
|
||||
|
||||
const GLModel::Geometry::EIndexType index_type = (triangles.size() < 65536) ? GLModel::Geometry::EIndexType::USHORT : GLModel::Geometry::EIndexType::UINT;
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3T2, index_type };
|
||||
|
||||
Vec2f min = triangles.front();
|
||||
Vec2f max = min;
|
||||
for (const Vec2f& v : triangles) {
|
||||
min = min.cwiseMin(v).eval();
|
||||
max = max.cwiseMax(v).eval();
|
||||
}
|
||||
|
||||
const Vec2f size = max - min;
|
||||
if (size.x() <= 0.0f || size.y() <= 0.0f)
|
||||
return;
|
||||
|
||||
Vec2f inv_size = size.cwiseInverse();
|
||||
inv_size.y() *= -1.0f;
|
||||
|
||||
unsigned int vertices_counter = 0;
|
||||
for (const Vec2f& v : triangles) {
|
||||
const Vec3f p = { v.x(), v.y(), GROUND_Z };
|
||||
init_data.add_vertex(p, (Vec2f)v.cwiseProduct(inv_size).eval());
|
||||
++vertices_counter;
|
||||
if (vertices_counter % 3 == 0) {
|
||||
if (index_type == GLModel::Geometry::EIndexType::USHORT)
|
||||
init_data.add_ushort_triangle((unsigned short)vertices_counter - 3, (unsigned short)vertices_counter - 2, (unsigned short)vertices_counter - 1);
|
||||
else
|
||||
init_data.add_uint_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
|
||||
}
|
||||
}
|
||||
|
||||
m_triangles.init_from(std::move(init_data));
|
||||
}
|
||||
|
||||
void Bed3D::init_gridlines()
|
||||
{
|
||||
if (m_gridlines.is_initialized())
|
||||
return;
|
||||
|
||||
if (m_contour.empty())
|
||||
return;
|
||||
|
||||
const BoundingBox& bed_bbox = m_contour.contour.bounding_box();
|
||||
const coord_t step = scale_(10.0);
|
||||
|
||||
Polylines axes_lines;
|
||||
for (coord_t x = bed_bbox.min.x(); x <= bed_bbox.max.x(); x += step) {
|
||||
Polyline line;
|
||||
line.append(Point(x, bed_bbox.min.y()));
|
||||
line.append(Point(x, bed_bbox.max.y()));
|
||||
axes_lines.push_back(line);
|
||||
}
|
||||
for (coord_t y = bed_bbox.min.y(); y <= bed_bbox.max.y(); y += step) {
|
||||
Polyline line;
|
||||
line.append(Point(bed_bbox.min.x(), y));
|
||||
line.append(Point(bed_bbox.max.x(), y));
|
||||
axes_lines.push_back(line);
|
||||
}
|
||||
|
||||
// clip with a slightly grown expolygon because our lines lay on the contours and may get erroneously clipped
|
||||
Lines gridlines = to_lines(intersection_pl(axes_lines, offset(m_contour, float(SCALED_EPSILON))));
|
||||
|
||||
// append bed contours
|
||||
Lines contour_lines = to_lines(m_contour);
|
||||
std::copy(contour_lines.begin(), contour_lines.end(), std::back_inserter(gridlines));
|
||||
|
||||
const GLModel::Geometry::EIndexType index_type = (gridlines.size() < 65536 / 2) ? GLModel::Geometry::EIndexType::USHORT : GLModel::Geometry::EIndexType::UINT;
|
||||
|
||||
GLModel::Geometry init_data;
|
||||
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3, index_type };
|
||||
|
||||
for (const Line& l : gridlines) {
|
||||
init_data.add_vertex(Vec3f(unscale<float>(l.a.x()), unscale<float>(l.a.y()), GROUND_Z));
|
||||
init_data.add_vertex(Vec3f(unscale<float>(l.b.x()), unscale<float>(l.b.y()), GROUND_Z));
|
||||
const unsigned int vertices_counter = (unsigned int)init_data.vertices_count();
|
||||
if (index_type == GLModel::Geometry::EIndexType::USHORT)
|
||||
init_data.add_ushort_line((unsigned short)vertices_counter - 2, (unsigned short)vertices_counter - 1);
|
||||
else
|
||||
init_data.add_uint_line(vertices_counter - 2, vertices_counter - 1);
|
||||
}
|
||||
|
||||
m_gridlines.init_from(std::move(init_data));
|
||||
}
|
||||
#else
|
||||
void Bed3D::calc_triangles(const ExPolygon& poly)
|
||||
{
|
||||
if (! m_triangles.set_from_triangles(triangulate_expolygon_2f(poly, NORMALS_UP), GROUND_Z))
|
||||
|
@ -320,6 +428,7 @@ void Bed3D::calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox)
|
|||
if (!m_gridlines.set_from_lines(gridlines, GROUND_Z))
|
||||
BOOST_LOG_TRIVIAL(error) << "Unable to create bed grid lines\n";
|
||||
}
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
// Try to match the print bed shape with the shape of an active profile. If such a match exists,
|
||||
// return the print bed model.
|
||||
|
@ -421,6 +530,44 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas)
|
|||
canvas.request_extra_frame();
|
||||
}
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
init_triangles();
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("printbed");
|
||||
if (shader != nullptr) {
|
||||
shader->start_using();
|
||||
shader->set_uniform("transparent_background", bottom);
|
||||
shader->set_uniform("svg_source", boost::algorithm::iends_with(m_texture.get_source(), ".svg"));
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
if (bottom)
|
||||
glsafe(::glDepthMask(GL_FALSE));
|
||||
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
if (bottom)
|
||||
glsafe(::glFrontFace(GL_CW));
|
||||
|
||||
// show the temporary texture while no compressed data is available
|
||||
GLuint tex_id = (GLuint)m_temp_texture.get_id();
|
||||
if (tex_id == 0)
|
||||
tex_id = (GLuint)m_texture.get_id();
|
||||
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, tex_id));
|
||||
m_triangles.render();
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, 0));
|
||||
|
||||
if (bottom)
|
||||
glsafe(::glFrontFace(GL_CCW));
|
||||
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
if (bottom)
|
||||
glsafe(::glDepthMask(GL_TRUE));
|
||||
|
||||
shader->stop_using();
|
||||
}
|
||||
#else
|
||||
if (m_triangles.get_vertices_count() > 0) {
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("printbed");
|
||||
if (shader != nullptr) {
|
||||
|
@ -488,6 +635,7 @@ void Bed3D::render_texture(bool bottom, GLCanvas3D& canvas)
|
|||
shader->stop_using();
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
}
|
||||
|
||||
void Bed3D::render_model()
|
||||
|
@ -541,6 +689,38 @@ void Bed3D::render_default(bool bottom, bool picking)
|
|||
{
|
||||
m_texture.reset();
|
||||
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
init_gridlines();
|
||||
init_triangles();
|
||||
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("flat");
|
||||
if (shader != nullptr) {
|
||||
shader->start_using();
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
if (m_model.get_filename().empty() && !bottom) {
|
||||
// draw background
|
||||
glsafe(::glDepthMask(GL_FALSE));
|
||||
m_triangles.set_color(picking ? PICKING_MODEL_COLOR : DEFAULT_MODEL_COLOR);
|
||||
m_triangles.render();
|
||||
glsafe(::glDepthMask(GL_TRUE));
|
||||
}
|
||||
|
||||
if (!picking) {
|
||||
// draw grid
|
||||
glsafe(::glLineWidth(1.5f * m_scale_factor));
|
||||
m_gridlines.set_color(picking ? DEFAULT_SOLID_GRID_COLOR : DEFAULT_TRANSPARENT_GRID_COLOR);
|
||||
m_gridlines.render();
|
||||
}
|
||||
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
|
||||
shader->stop_using();
|
||||
}
|
||||
#else
|
||||
const unsigned int triangles_vcount = m_triangles.get_vertices_count();
|
||||
if (triangles_vcount > 0) {
|
||||
const bool has_model = !m_model.get_filename().empty();
|
||||
|
@ -573,8 +753,10 @@ void Bed3D::render_default(bool bottom, bool picking)
|
|||
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
}
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
}
|
||||
|
||||
#if !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
void Bed3D::release_VBOs()
|
||||
{
|
||||
if (m_vbo_id > 0) {
|
||||
|
@ -582,6 +764,7 @@ void Bed3D::release_VBOs()
|
|||
m_vbo_id = 0;
|
||||
}
|
||||
}
|
||||
#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
} // GUI
|
||||
} // Slic3r
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
#include "3DScene.hpp"
|
||||
#include "GLModel.hpp"
|
||||
|
||||
#include <libslic3r/BuildVolume.hpp>
|
||||
#include "libslic3r/BuildVolume.hpp"
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
#include "libslic3r/ExPolygon.hpp"
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
#include <tuple>
|
||||
#include <array>
|
||||
|
@ -15,6 +18,7 @@ namespace GUI {
|
|||
|
||||
class GLCanvas3D;
|
||||
|
||||
#if !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
class GeometryBuffer
|
||||
{
|
||||
struct Vertex
|
||||
|
@ -36,6 +40,7 @@ public:
|
|||
size_t get_tex_coords_offset() const { return (size_t)(3 * sizeof(float)); }
|
||||
unsigned int get_vertices_count() const { return (unsigned int)m_vertices.size(); }
|
||||
};
|
||||
#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
class Bed3D
|
||||
{
|
||||
|
@ -79,23 +84,38 @@ private:
|
|||
std::string m_model_filename;
|
||||
// Print volume bounding box exteded with axes and model.
|
||||
BoundingBoxf3 m_extended_bounding_box;
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
// Print bed polygon
|
||||
ExPolygon m_contour;
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
// Slightly expanded print bed polygon, for collision detection.
|
||||
Polygon m_polygon;
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
GLModel m_triangles;
|
||||
GLModel m_gridlines;
|
||||
#else
|
||||
GeometryBuffer m_triangles;
|
||||
GeometryBuffer m_gridlines;
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
GLTexture m_texture;
|
||||
// temporary texture shown until the main texture has still no levels compressed
|
||||
GLTexture m_temp_texture;
|
||||
GLModel m_model;
|
||||
Vec3d m_model_offset{ Vec3d::Zero() };
|
||||
#if !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
unsigned int m_vbo_id{ 0 };
|
||||
#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
Axes m_axes;
|
||||
|
||||
float m_scale_factor{ 1.0f };
|
||||
|
||||
public:
|
||||
Bed3D() = default;
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
~Bed3D() = default;
|
||||
#else
|
||||
~Bed3D() { release_VBOs(); }
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
|
||||
// Update print bed model from configuration.
|
||||
// Return true if the bed shape changed, so the calee will update the UI.
|
||||
|
@ -125,8 +145,13 @@ public:
|
|||
private:
|
||||
// Calculate an extended bounding box from axes and current model for visualization purposes.
|
||||
BoundingBoxf3 calc_extended_bounding_box() const;
|
||||
#if ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
void init_triangles();
|
||||
void init_gridlines();
|
||||
#else
|
||||
void calc_triangles(const ExPolygon& poly);
|
||||
void calc_gridlines(const ExPolygon& poly, const BoundingBox& bed_bbox);
|
||||
#endif // ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
static std::tuple<Type, std::string, std::string> detect_type(const Pointfs& shape);
|
||||
void render_internal(GLCanvas3D& canvas, bool bottom, float scale_factor,
|
||||
bool show_axes, bool show_texture, bool picking);
|
||||
|
@ -136,7 +161,9 @@ private:
|
|||
void render_model();
|
||||
void render_custom(GLCanvas3D& canvas, bool bottom, bool show_texture, bool picking);
|
||||
void render_default(bool bottom, bool picking);
|
||||
#if !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
void release_VBOs();
|
||||
#endif // !ENABLE_GLBEGIN_GLEND_REMOVAL
|
||||
};
|
||||
|
||||
} // GUI
|
||||
|
|
|
@ -42,6 +42,16 @@ void GLModel::Geometry::add_vertex(const Vec3f& position)
|
|||
vertices.emplace_back(position.z());
|
||||
}
|
||||
|
||||
void GLModel::Geometry::add_vertex(const Vec3f& position, const Vec2f& tex_coord)
|
||||
{
|
||||
assert(format.vertex_layout == EVertexLayout::P3T2);
|
||||
vertices.emplace_back(position.x());
|
||||
vertices.emplace_back(position.y());
|
||||
vertices.emplace_back(position.z());
|
||||
vertices.emplace_back(tex_coord.x());
|
||||
vertices.emplace_back(tex_coord.y());
|
||||
}
|
||||
|
||||
void GLModel::Geometry::add_vertex(const Vec3f& position, const Vec3f& normal)
|
||||
{
|
||||
assert(format.vertex_layout == EVertexLayout::P3N3);
|
||||
|
@ -228,6 +238,7 @@ size_t GLModel::Geometry::vertex_stride_floats(const Format& format)
|
|||
case EVertexLayout::P2: { return 2; }
|
||||
case EVertexLayout::P2T2: { return 4; }
|
||||
case EVertexLayout::P3: { return 3; }
|
||||
case EVertexLayout::P3T2: { return 5; }
|
||||
case EVertexLayout::P3N3: { return 6; }
|
||||
default: { assert(false); return 0; }
|
||||
};
|
||||
|
@ -240,6 +251,7 @@ size_t GLModel::Geometry::position_stride_floats(const Format& format)
|
|||
case EVertexLayout::P2:
|
||||
case EVertexLayout::P2T2: { return 2; }
|
||||
case EVertexLayout::P3:
|
||||
case EVertexLayout::P3T2:
|
||||
case EVertexLayout::P3N3: { return 3; }
|
||||
default: { assert(false); return 0; }
|
||||
};
|
||||
|
@ -252,6 +264,7 @@ size_t GLModel::Geometry::position_offset_floats(const Format& format)
|
|||
case EVertexLayout::P2:
|
||||
case EVertexLayout::P2T2:
|
||||
case EVertexLayout::P3:
|
||||
case EVertexLayout::P3T2:
|
||||
case EVertexLayout::P3N3: { return 0; }
|
||||
default: { assert(false); return 0; }
|
||||
};
|
||||
|
@ -279,7 +292,8 @@ size_t GLModel::Geometry::tex_coord_stride_floats(const Format& format)
|
|||
{
|
||||
switch (format.vertex_layout)
|
||||
{
|
||||
case EVertexLayout::P2T2: { return 2; }
|
||||
case EVertexLayout::P2T2:
|
||||
case EVertexLayout::P3T2: { return 2; }
|
||||
default: { assert(false); return 0; }
|
||||
};
|
||||
}
|
||||
|
@ -289,6 +303,7 @@ size_t GLModel::Geometry::tex_coord_offset_floats(const Format& format)
|
|||
switch (format.vertex_layout)
|
||||
{
|
||||
case EVertexLayout::P2T2: { return 2; }
|
||||
case EVertexLayout::P3T2: { return 3; }
|
||||
default: { assert(false); return 0; }
|
||||
};
|
||||
}
|
||||
|
@ -310,6 +325,7 @@ bool GLModel::Geometry::has_position(const Format& format)
|
|||
case EVertexLayout::P2:
|
||||
case EVertexLayout::P2T2:
|
||||
case EVertexLayout::P3:
|
||||
case EVertexLayout::P3T2:
|
||||
case EVertexLayout::P3N3: { return true; }
|
||||
default: { assert(false); return false; }
|
||||
};
|
||||
|
@ -321,7 +337,8 @@ bool GLModel::Geometry::has_normal(const Format& format)
|
|||
{
|
||||
case EVertexLayout::P2:
|
||||
case EVertexLayout::P2T2:
|
||||
case EVertexLayout::P3: { return false; }
|
||||
case EVertexLayout::P3:
|
||||
case EVertexLayout::P3T2: { return false; }
|
||||
case EVertexLayout::P3N3: { return true; }
|
||||
default: { assert(false); return false; }
|
||||
};
|
||||
|
@ -331,7 +348,8 @@ bool GLModel::Geometry::has_tex_coord(const Format& format)
|
|||
{
|
||||
switch (format.vertex_layout)
|
||||
{
|
||||
case EVertexLayout::P2T2: { return true; }
|
||||
case EVertexLayout::P2T2:
|
||||
case EVertexLayout::P3T2: { return true; }
|
||||
case EVertexLayout::P2:
|
||||
case EVertexLayout::P3:
|
||||
case EVertexLayout::P3N3: { return false; }
|
||||
|
|
|
@ -58,6 +58,7 @@ namespace GUI {
|
|||
P2, // position 2 floats
|
||||
P2T2, // position 2 floats + texture coords 2 floats
|
||||
P3, // position 3 floats
|
||||
P3T2, // position 3 floats + texture coords 2 floats
|
||||
P3N3, // position 3 floats + normal 3 floats
|
||||
};
|
||||
|
||||
|
@ -82,6 +83,7 @@ namespace GUI {
|
|||
void add_vertex(const Vec2f& position);
|
||||
void add_vertex(const Vec2f& position, const Vec2f& tex_coord);
|
||||
void add_vertex(const Vec3f& position);
|
||||
void add_vertex(const Vec3f& position, const Vec2f& tex_coord);
|
||||
void add_vertex(const Vec3f& position, const Vec3f& normal);
|
||||
|
||||
void add_ushort_index(unsigned short id);
|
||||
|
|
|
@ -871,8 +871,8 @@ void GUI_App::init_app_config()
|
|||
{
|
||||
// Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release.
|
||||
// SetAppName(SLIC3R_APP_KEY);
|
||||
// SetAppName(SLIC3R_APP_KEY "-alpha");
|
||||
SetAppName(SLIC3R_APP_KEY "-beta");
|
||||
SetAppName(SLIC3R_APP_KEY "-alpha");
|
||||
// SetAppName(SLIC3R_APP_KEY "-beta");
|
||||
// SetAppDisplayName(SLIC3R_APP_NAME);
|
||||
|
||||
// Set the Slic3r data directory at the Slic3r XS module.
|
||||
|
|
|
@ -95,9 +95,9 @@ wxButton* MsgDialog::get_button(wxWindowID btn_id){
|
|||
void MsgDialog::apply_style(long style)
|
||||
{
|
||||
if (style & wxOK) add_button(wxID_OK, true);
|
||||
if (style & wxYES) add_button(wxID_YES, true);
|
||||
if (style & wxNO) add_button(wxID_NO);
|
||||
if (style & wxCANCEL) add_button(wxID_CANCEL);
|
||||
if (style & wxYES) add_button(wxID_YES, !(style & wxNO_DEFAULT));
|
||||
if (style & wxNO) add_button(wxID_NO, (style & wxNO_DEFAULT));
|
||||
if (style & wxCANCEL) add_button(wxID_CANCEL, (style & wxCANCEL_DEFAULT));
|
||||
|
||||
logo->SetBitmap( create_scaled_bitmap(style & wxICON_WARNING ? "exclamation" :
|
||||
style & wxICON_INFORMATION ? "info" :
|
||||
|
@ -299,25 +299,12 @@ wxString get_wraped_wxString(const wxString& in, size_t line_len /*=80*/)
|
|||
for (size_t i = 0; i < in.size();) {
|
||||
// Overwrite the character (space or newline) starting at ibreak?
|
||||
bool overwrite = false;
|
||||
#if wxUSE_UNICODE_WCHAR
|
||||
// On Windows, most likely the internal representation of wxString is wide char.
|
||||
size_t end = std::min(in.size(), i + line_len);
|
||||
size_t ibreak = end;
|
||||
for (size_t j = i; j < end; ++ j) {
|
||||
if (bool newline = in[j] == '\n'; in[j] == ' ' || in[j] == '\t' || newline) {
|
||||
ibreak = j;
|
||||
overwrite = true;
|
||||
if (newline)
|
||||
break;
|
||||
} else if (in[j] == '/' || in[j] == '\\')
|
||||
ibreak = j + 1;
|
||||
}
|
||||
#else
|
||||
// UTF8 representation of wxString.
|
||||
// Where to break the line, index of character at the start of a UTF-8 sequence.
|
||||
size_t ibreak = size_t(-1);
|
||||
// Overwrite the character at ibreak (it is a whitespace) or not?
|
||||
for (size_t cnt = 0, j = i; j < in.size();) {
|
||||
size_t j = i;
|
||||
for (size_t cnt = 0; j < in.size();) {
|
||||
if (bool newline = in[j] == '\n'; in[j] == ' ' || in[j] == '\t' || newline) {
|
||||
// Overwrite the whitespace.
|
||||
ibreak = j ++;
|
||||
|
@ -326,16 +313,23 @@ wxString get_wraped_wxString(const wxString& in, size_t line_len /*=80*/)
|
|||
break;
|
||||
} else if (in[j] == '/') {
|
||||
// Insert after the slash.
|
||||
ibreak = ++ j;
|
||||
ibreak = ++ j;
|
||||
overwrite = false;
|
||||
} else
|
||||
j += get_utf8_sequence_length(in.c_str() + j, in.size() - j);
|
||||
if (++ cnt == line_len) {
|
||||
if (ibreak == size_t(-1))
|
||||
ibreak = j;
|
||||
if (ibreak == size_t(-1)) {
|
||||
ibreak = j;
|
||||
overwrite = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (j == in.size()) {
|
||||
out.append(in.begin() + i, in.end());
|
||||
break;
|
||||
}
|
||||
assert(ibreak != size_t(-1));
|
||||
out.append(in.begin() + i, in.begin() + ibreak);
|
||||
out.append('\n');
|
||||
i = ibreak;
|
||||
|
|
|
@ -4112,7 +4112,10 @@ wxSizer* TabPrint::create_manage_substitution_widget(wxWindow* parent)
|
|||
});
|
||||
|
||||
create_btn(&m_del_all_substitutions_btn, _L("Delete all"), "cross");
|
||||
m_del_all_substitutions_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent e) {
|
||||
m_del_all_substitutions_btn->Bind(wxEVT_BUTTON, [this, parent](wxCommandEvent e) {
|
||||
if (MessageDialog(parent, _L("Are you sure you want to delete all substitutions?"), SLIC3R_APP_NAME, wxYES_NO | wxICON_QUESTION).
|
||||
ShowModal() != wxID_YES)
|
||||
return;
|
||||
m_subst_manager.delete_all();
|
||||
m_del_all_substitutions_btn->Hide();
|
||||
});
|
||||
|
|
|
@ -656,6 +656,7 @@ void DiffViewCtrl::Clear()
|
|||
{
|
||||
model->Clear();
|
||||
m_items_map.clear();
|
||||
m_has_long_strings = false;
|
||||
}
|
||||
|
||||
wxString DiffViewCtrl::get_short_string(wxString full_string)
|
||||
|
@ -1523,8 +1524,8 @@ DiffPresetDialog::DiffPresetDialog(MainFrame* mainframe)
|
|||
topSizer->Add(m_top_info_line, 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, 2 * border);
|
||||
topSizer->Add(presets_sizer, 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, border);
|
||||
topSizer->Add(m_show_all_presets, 0, wxEXPAND | wxALL, border);
|
||||
topSizer->Add(m_bottom_info_line, 0, wxEXPAND | wxALL, 2 * border);
|
||||
topSizer->Add(m_tree, 1, wxEXPAND | wxALL, border);
|
||||
topSizer->Add(m_bottom_info_line, 0, wxEXPAND | wxALL, 2 * border);
|
||||
|
||||
this->SetMinSize(wxSize(80 * em, 30 * em));
|
||||
this->SetSizer(topSizer);
|
||||
|
@ -1689,12 +1690,17 @@ void DiffPresetDialog::update_tree()
|
|||
left_val, right_val, category_icon_map.at(option.category));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_tree->has_long_strings())
|
||||
bottom_info = _L("Some fields are too long to fit. Right mouse click reveals the full text.");
|
||||
|
||||
bool tree_was_shown = m_tree->IsShown();
|
||||
m_tree->Show(show_tree);
|
||||
if (!show_tree)
|
||||
|
||||
bool show_bottom_info = !show_tree || m_tree->has_long_strings();
|
||||
if (show_bottom_info)
|
||||
m_bottom_info_line->SetLabel(bottom_info);
|
||||
m_bottom_info_line->Show(!show_tree);
|
||||
m_bottom_info_line->Show(show_bottom_info);
|
||||
|
||||
if (tree_was_shown == m_tree->IsShown())
|
||||
Layout();
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
set(SLIC3R_APP_NAME "PrusaSlicer")
|
||||
set(SLIC3R_APP_KEY "PrusaSlicer")
|
||||
set(SLIC3R_VERSION "2.4.1-beta1")
|
||||
set(SLIC3R_VERSION "2.5.0-alpha0")
|
||||
set(SLIC3R_BUILD_ID "PrusaSlicer-${SLIC3R_VERSION}+UNKNOWN")
|
||||
set(SLIC3R_RC_VERSION "2,4,1,0")
|
||||
set(SLIC3R_RC_VERSION_DOTS "2.4.1.0")
|
||||
set(SLIC3R_RC_VERSION "2,5,0,0")
|
||||
set(SLIC3R_RC_VERSION_DOTS "2.5.0.0")
|
||||
|
|
|
@ -208,5 +208,36 @@ if (MSVC)
|
|||
else ()
|
||||
set(PERL_PROVE "${PERL_BIN_PATH}/prove")
|
||||
endif ()
|
||||
add_test (NAME xs COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} -I ${PERL_LOCAL_LIB_DIR}/lib/perl5 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
|
||||
add_test (NAME integration COMMAND "${PERL_EXECUTABLE}" ${PERL_PROVE} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/..)
|
||||
|
||||
set(PERL_ENV_VARS "")
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
|
||||
if (SLIC3R_ASAN OR SLIC3R_UBSAN)
|
||||
set(PERL_ENV_VARS env)
|
||||
endif ()
|
||||
|
||||
if (SLIC3R_ASAN)
|
||||
# Find the location of libasan.so for passing it into LD_PRELOAD. It works with GCC and Clang on Linux.
|
||||
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=libasan.so OUTPUT_VARIABLE LIBASAN_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(PERL_ENV_VARS ${PERL_ENV_VARS} "LD_PRELOAD=${LIBASAN_PATH}")
|
||||
|
||||
# Suppressed memory leak reports that come from Perl.
|
||||
set(PERL_LEAK_SUPPRESSION_FILE ${CMAKE_CURRENT_BINARY_DIR}/leak_suppression.txt)
|
||||
file(WRITE ${PERL_LEAK_SUPPRESSION_FILE}
|
||||
"leak:Perl_safesysmalloc\n"
|
||||
"leak:Perl_safesyscalloc\n"
|
||||
"leak:Perl_safesysrealloc\n"
|
||||
"leak:__newlocale\n")
|
||||
|
||||
# Suppress a few memory leak reports and disable informing about suppressions.
|
||||
# Print reports about memory leaks but exit with zero exit code when any memory leaks is found to make unit tests pass.
|
||||
set(PERL_ENV_VARS ${PERL_ENV_VARS} "LSAN_OPTIONS=suppressions=${PERL_LEAK_SUPPRESSION_FILE}:print_suppressions=0:exitcode=0")
|
||||
endif ()
|
||||
|
||||
if (SLIC3R_UBSAN)
|
||||
# Do not show full stacktrace for reports from UndefinedBehaviorSanitizer in Perl tests.
|
||||
set(PERL_ENV_VARS ${PERL_ENV_VARS} "UBSAN_OPTIONS=print_stacktrace=0")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
add_test (NAME xs COMMAND ${PERL_ENV_VARS} "${PERL_EXECUTABLE}" ${PERL_PROVE} -I ${PERL_LOCAL_LIB_DIR}/lib/perl5 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
|
||||
add_test (NAME integration COMMAND ${PERL_ENV_VARS} "${PERL_EXECUTABLE}" ${PERL_PROVE} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/..)
|
||||
|
|
Loading…
Add table
Reference in a new issue