Belt printer: no layer changes that print nothing, and a preview that survives them

Since the slicing frame of a belt object starts at the belt below its
leading end, its first layers are empty.  On a single part they carry
the brim bands; with several parts along the belt the later parts'
empty layers fall between the earlier parts' printing layers and were
written to the G-code as layer changes with no moves at all.  The
preview numbers its layers (libvgcode::Layers) from the vertices it is
given and expects consecutive ids, so at the first such gap it stopped
creating layers and folded everything after it into the last one: the
top slider layer held nearly the whole print, the slider jumped every
other layer through the single-colour stretch before a second part on
another filament, and with the belt purge tower the whole print greyed
out while dragging.

Drop the belt layers that print nothing (no object, support or brim
content) in GCode::collect_layers_to_print, and renumber the layers
consecutively over the moves that exist when converting a result for
libvgcode, so a file with empty layers from any source still previews
correctly.  The layer slider labels a belt layer with its print Z (the
slicer's layer Z, which increases along the belt) instead of libvgcode's
toolpath height, which on a tilted layer is wherever its last extrusion
ended; the slider assumes that list increases and showed "0 / max" on
alternate layers.  The processor reads that print Z from the ";Z:" tag
non-BBL printers write (it only knew "; Z_HEIGHT:"), on belt printers
only, so nothing changes elsewhere.  Regression test: two cubes 60 mm apart along the
belt produce no layer without an extrusion and the header's layer count
matches.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
harrierpigeon
2026-10-07 03:50:51 -05:00
co-authored by Claude Fable 5.1
parent 6927475499
commit f64b49ab52
6 changed files with 147 additions and 4 deletions
+18 -4
View File
@@ -17,6 +17,8 @@
#include "libslic3r/libslic3r.h"
#include "LibVGCodeWrapper.hpp"
#include <limits>
#include "libslic3r/Print.hpp"
#include "libslic3r/Color.hpp"
#include "libslic3r/CustomGCode.hpp"
@@ -230,10 +232,22 @@ GCodeInputData convert(const Slic3r::GCodeProcessorResult& result, const std::ve
const std::vector<Slic3r::GCodeProcessorResult::MoveVertex>& moves = result.moves;
ret.vertices.reserve(2 * moves.size());
// libvgcode numbers its layers from the vertices it is given and expects them to
// arrive one layer after the other with consecutive ids: a layer without any move
// (a belt file can carry layer changes that print nothing) would leave a gap, and
// every later vertex would then be folded into the last layer created. Renumber
// the ids consecutively over the moves that exist.
uint32_t src_layer_id = std::numeric_limits<uint32_t>::max();
uint32_t layer_id = 0;
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);
if (curr.layer_id != src_layer_id) {
if (src_layer_id != std::numeric_limits<uint32_t>::max())
++ layer_id;
src_layer_id = curr.layer_id;
}
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
@@ -245,7 +259,7 @@ GCodeInputData convert(const Slic3r::GCodeProcessorResult& result, const std::ve
#if VGCODE_ENABLE_COG_AND_TOOL_MARKERS
const libvgcode::PathVertex vertex = { xform_pos(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<uint32_t>(curr.gcode_id), layer_id,
static_cast<uint8_t>(curr.extruder_id), static_cast<uint8_t>(curr.cp_color_id), { 0.0f, 0.0f },
/* ORCA: Add Pressure Advance visualization support */ 0.0f, curr.pressure_advance,
/* ORCA: Add Acceleration visualization support */ curr.acceleration,
@@ -253,7 +267,7 @@ GCodeInputData convert(const Slic3r::GCodeProcessorResult& result, const std::ve
#else
const libvgcode::PathVertex vertex = { xform_pos(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<uint32_t>(curr.gcode_id), layer_id,
static_cast<uint8_t>(curr.extruder_id), static_cast<uint8_t>(curr.cp_color_id), { 0.0f, 0.0f },
/* ORCA: Add Pressure Advance visualization support */ 0.0f, curr.pressure_advance,
/* ORCA: Add Acceleration visualization support */ curr.acceleration,
@@ -267,7 +281,7 @@ GCodeInputData convert(const Slic3r::GCodeProcessorResult& result, const std::ve
const libvgcode::PathVertex vertex = { xform_pos(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),
convert(curr.extrusion_role), curr_type, static_cast<uint32_t>(curr.gcode_id), layer_id,
static_cast<uint8_t>(curr.extruder_id), static_cast<uint8_t>(curr.cp_color_id), curr.time,
/* ORCA: Add Pressure Advance visualization support */ 0.0f, curr.pressure_advance,
/* ORCA: Add Acceleration visualization support */ curr.acceleration,
@@ -275,7 +289,7 @@ GCodeInputData convert(const Slic3r::GCodeProcessorResult& result, const std::ve
#else
const libvgcode::PathVertex vertex = { xform_pos(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<uint32_t>(curr.gcode_id), layer_id,
static_cast<uint8_t>(curr.extruder_id), static_cast<uint8_t>(curr.cp_color_id), curr.time,
/* ORCA: Add Pressure Advance visualization support */ 0.0f, curr.pressure_advance,
/* ORCA: Add Acceleration visualization support */ curr.acceleration,