Part 2: Replace belt rotation w/ per-axis shear transforms and G-code axis remap

- Replace monolithic belt rotation transform with independent per-axis
    shear controls (mode/angle/source-axis for X, Y, Z) and G-code axis
    remapping, giving full flexibility to match any belt printer's
    coordinate system
  - Remove all rotation mode logic and intermediate type+axes dropdowns,
    simplifying the pipeline to pure shear matrices while preserving the
    default behavior (Y += Z*cot(45deg) with identity remap)
  - Clean up GCodeWriter, GCodeProcessor, and GCodeViewer for the new
    shear-only model; expose 12 new settings in printer UI via
    Tab.cpp/Preset.cpp

Implement belt printer tilted slicing

Implement the core belt slicing pipeline that makes the slicer
tilt-aware:

Step 1: GCodeWriter::to_machine_coords() - R(+alpha, X) rotation
  from slicing frame to machine frame
Step 2: PrintObject - belt-rotated object height calculation
  (y*sin(a) + z*cos(a)) for correct layer count
Step 3: PrintObjectSlice - apply R(-alpha, X) rotation trafo so
  horizontal slice planes correspond to belt-parallel planes,
  with Z-shift computed from model volumes
Step 4: GCodeProcessor - machine-frame preview (no transform needed)
Step 5: 3DBed - rotate bed visualization about X by belt angle

Fix: belt surface IS the build plate, no mesh rotation

Currently still slicing perpendicular to the belt normal.  Need to figure out why.

Fix G-code Z sign: use R(-alpha, X) so Z+ is away from belt

The previous R(+alpha, X) transform produced negative Z values
(-y*sin(a) term dominated). Changed to R(-alpha, X) which gives
machine_z = y*sin(a) + z*cos(a), always positive for points
above the belt surface. Z increases with each layer as expected.

reverting and changing slice methodology

Add pink slicing direction arrow from origin

Shows the effective slicing direction (gantry normal) as a pink
arrow from the origin. Shorter and wider than the gravity arrow.
Direction: R(+alpha, X) * Z = (0, -sin(a), cos(a)), which is
the layer stacking direction in the original mesh frame.

Fix slicing arrow visibility and add raw G-code toggle

- Disable depth test for pink slicing arrow so it renders on top of
  the tilted bed geometry (was being occluded)
- Remove unnecessary 5mm Z-offset from arrow position
- Add m_belt_show_raw toggle to GCodeViewer
- Add "Show raw G-code (slicing frame)" checkbox in legend when
  belt mode is active

Implement to_machine_coords inverse rotation for belt printer G-code

The slicing pipeline rotates the mesh by R(-alpha, X) and shifts Z to
start at 0. The G-code output now undoes this transform via
to_machine_coords: R(+alpha, X) * T(0,0,+z_shift), recovering the
original machine-frame coordinates where Y is horizontal and Z is
vertical.

Changes:
- GCodeWriter: implement to_machine_coords with inverse rotation + Z-shift
- GCodeWriter: add belt_z_shift member and setter/getter
- GCode.cpp: compute Z-shift from print objects (same logic as
  PrintObjectSlice) and pass to writer; write z_shift to G-code header
- GCodeProcessor: parse belt_z_shift from G-code header
- GCodeViewer: store belt_z_shift from processor result

Wire raw G-code toggle to apply slicing-frame view transform

When "Show raw G-code (slicing frame)" is checked in the preview
legend, the view matrix is modified to apply R(-alpha, X) * T(0,0,-z_shift)
to the toolpath rendering. This shows the G-code as it was during
slicing: rotated part with horizontal layers.

Default (unchecked): machine-frame view — upright part with tilted layers.

Remove belt printer placeholder comment from GCodeProcessor

The preview now correctly displays machine-frame G-code with the
optional raw view toggle. No transform is needed in the processor.
This commit is contained in:
harrierpigeon
2026-04-09 23:07:06 -05:00
parent c808653565
commit 501aff7e53
11 changed files with 183 additions and 21 deletions
+25 -2
View File
@@ -8,6 +8,7 @@
#include "Exception.hpp"
#include "ExtrusionEntity.hpp"
#include "EdgeGrid.hpp"
#include "Geometry.hpp"
#include "Geometry/ConvexHull.hpp"
#include "GCode/PrintExtents.hpp"
#include "GCode/Thumbnails.hpp"
@@ -2414,8 +2415,28 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
m_writer.set_is_bbl_machine(is_bbl_printers);
// Belt printer: initialize coordinate transformation on the writer.
if (print.config().belt_printer.value)
if (print.config().belt_printer.value) {
m_writer.set_belt_angle(print.config().belt_printer_angle.value);
// Compute the Z-shift that was applied during slicing (same logic as PrintObjectSlice.cpp).
// This is needed by to_machine_coords() to undo the slicing transform.
// For multiple objects, use the minimum min_z_rotated across all objects.
double angle_rad = Geometry::deg2rad(print.config().belt_printer_angle.value);
Transform3d belt_rotation = Transform3d::Identity();
belt_rotation.rotate(Eigen::AngleAxisd(-angle_rad, Vec3d::UnitX()));
double global_min_z = std::numeric_limits<double>::max();
for (const PrintObject *obj : print.objects()) {
Transform3d obj_trafo = belt_rotation * obj->trafo_centered();
for (const ModelVolume *mv : obj->model_object()->volumes) {
if (! mv->is_model_part() && ! mv->is_modifier())
continue;
BoundingBoxf3 bb = mv->mesh().bounding_box();
bb = bb.transformed(obj_trafo * mv->get_matrix());
global_min_z = std::min(global_min_z, bb.min.z());
}
}
if (global_min_z != std::numeric_limits<double>::max() && std::abs(global_min_z) > EPSILON)
m_writer.set_belt_z_shift(global_min_z); // typically negative
}
// How many times will be change_layer() called?
// change_layer() in turn increments the progress bar status.
@@ -2507,8 +2528,10 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
// Write information on the generator.
file.write_format("; generated by %s on %s\n", Slic3r::header_slic3r_generated().c_str(), Slic3r::Utils::local_timestamp().c_str());
// Belt printer: embed angle in header for G-code processor detection.
if (print.config().belt_printer.value)
if (print.config().belt_printer.value) {
file.write_format("; belt_printer_angle = %.1f\n", print.config().belt_printer_angle.value);
file.write_format("; belt_z_shift = %.4f\n", m_writer.belt_z_shift());
}
if (is_bbl_printers)
file.write_format(";%s\n", GCodeProcessor::reserved_tag(GCodeProcessor::ETags::Estimated_Printing_Time_Placeholder).c_str());
//BBS: total layer number