The Cartesian designed-view preview over-extended the toolpaths past the model
shell by a height-proportional amount (up to ~20mm tall parts), most visibly on
long multi-part prints; compact parts like a calibration cube looked fine.
Two coupled causes:
- Belt start G-code that primes with a Z advance and a 'G92 Z0' reset leaves a
constant machine-Z origin in the GCodeProcessor, so move positions are stored as
gcode_Z + origin. The linear back-transform mixes that constant with the
gantry-Y term, leaving a per-move designed-Y error that min-corner anchoring
cannot cancel when an elevated move (e.g. a bridge) happens to cancel it at the
bbox minimum. Expose GCodeProcessorResult::belt_z_origin (the m_origin[Z] left by
the start G-code) and subtract it before the back-transform.
- Elevated features (bridges/overhangs) are mis-mapped by the linear inverse to
outside the model body; build the anchor bbox only from moves within model_bb +/-
10mm, with a fallback to the full bbox when the clip would drop the bulk (object
placed away from the belt entry) so the gross-offset case still anchors.
Preview-only; G-code output is unchanged.
perf(GCodeProcessor): stop recompiling std::regex on every g-code line
process_SET_VELOCITY_LIMIT() constructed three std::regex objects from
scratch on every call, and Klipper-flavor g-code contains
SET_VELOCITY_LIMIT on a large share of lines (8,834 of 103,549 lines for
a single 3DBenchy sliced for a Creality K2). perf attributes 6.4% of the
whole slicing run to this one function, almost all of it regex
compilation and the allocator traffic it generates.
process_SET_PRESSURE_ADVANCE() and the External_Purge_Tag handler had
the same per-call construction.
Hoist all five patterns to function-local static const std::regex so
they compile once. Generated g-code is byte-identical (modulo the
timestamp header); slicing a 16x Benchy plate for a K2 drops from
78.5s to 27.3s wall (2.9x) on a 16-core Linux box, single Benchy from
8.9s to 5.6s.
Co-authored-by: grant0013 <grant@harktech.co.uk>
* fix: restore BuildVolume bounds when toggling belt mode
set_belt_printer() mutated m_bboxf when enabling but never restored
the original extents on disable or when switching infinite_y true->false,
leaving stale max.y/max.z values that broke collision and object_state
checks. Recompute m_bboxf from m_bed_shape + m_max_print_height at the
top of each call, then apply belt-specific adjustments on top.
Addresses Copilot review comment on PR #12998 (BuildVolume.cpp:196).
* chore: drop [BELT-DEBUG] to_machine_coords log to trace
Was emitting at warning level once per 0.2mm Z bucket during every belt
print export, polluting default user logs. Trace level matches the rest
of the belt diagnostics and is silent in production.
Addresses Copilot review comment on PR #12998 (BeltGCodeWriter.cpp:86).
* chore: drop [BELTRACE] make_perimeters/support logs to trace
Eight warning-level traces around make_perimeters and
generate_support_material were emitting on every call/exit during normal
slicing, cluttering default logs. They're concurrency-debug breadcrumbs
not user-facing diagnostics, so drop them to trace.
Addresses Copilot review comment on PR #12998 (PrintObject.cpp:438).
* perf: gate BeltSliceStrategy diagnostic bbox tracking behind compile flag
apply_to_trafo() walked every model vertex twice (once for min_z, once
for per-volume mesh/slicer bboxes) and emitted seven trace logs per
call. The bboxes and logs are diagnostic only; min_z is the load-bearing
output. Wrap the bbox accumulation, logging, and supporting headers in
SLIC3R_BELT_DIAGNOSTIC_LOG so production builds do the bare min_z scan.
Addresses Copilot review comment on PR #12998 (BeltSliceStrategy.cpp:95).
* fix: apply part_cooling_fan_min_pwm to first-layer plane fan crossings
apply_first_layer_plane_fan_eval emitted band-crossing M106 commands
through GCodeWriter::set_fan() without the per-printer PWM floor that
every other set_fan call in CoolingBuffer applies. On printers with a
non-zero part_cooling_fan_min_pwm, fans could fail to spin up at low
requested speeds near the belt surface.
Addresses Copilot review comment on PR #12998 (CoolingBuffer.cpp:1227).
* initial commit
* fix upper bounds for assemblies
* significantly less Z shift issues, still not quite tamped down yet though
* add instrumentation to logs
* finally found the issue
* update printer defaults
* feat(viewer): Display travel distance and move count in G-code summary
This commit introduces a new feature that enhances the G-code viewer by displaying the total travel distance and the total number of travel moves in the 'Line Type' summary.
This provides users with more detailed statistics about their prints, helping them to better understand the printer's behavior and identify opportunities to optimize travel moves for faster print times.
This commit also fixes a critical bug in the G-code processor where the travel distance was being calculated incorrectly. The distance variable was not being updated for non-extruding travel moves, leading to inaccurate statistics. The calculation has been corrected to ensure it is performed for all relevant move types, resulting in accurate travel distance reporting.
* Subfix segments
kilo mega giga tera peta exa
* Add missing values
* Grams to Kilos and tons
* add distance
* Fix tool view
* Record and display seam distances
Track seam-related distances in print statistics and show them in the GCode viewer. Added total_seam_gap_distance and total_seam_scarf_distance to PrintEstimatedStatistics (with initialization). In GCode::extrude_loop the code now computes seam gap and scarf distances and accumulates them for external perimeters. GCodeViewer uses the summed seam distance when the Seams option is selected in the legend.
* Fix travel / wipe distances
* Update GCode.cpp
* Filament changes estimated time
---------
Co-authored-by: Steve Scargall <37674041+sscargal@users.noreply.github.com>
Reconciles the belt-printer branch with upstream PRs through #13723. Six
files had conflicts; three additional files needed manual follow-up fixes
where the auto-merge produced code that referenced upstream-renamed fields
or changed function signatures.
Notable reconciliations:
- TreeSupport.cpp: kept belt-floor early-exit branches around HEAD's
drop-down logic, folded upstream's `(distance_to_top > 0 ? 1 : 0)`
formula into the non-belt-floor path (upstream PR #11812). Dropped dead
`roof_enabled`/`force_tip_to_roof` locals.
- TreeSupport3D.cpp: combined upstream's safety-offset + remove_small
changes with HEAD's belt-floor clip in the per-slice trim loop. Dropped
HEAD's `else` block (superseded by upstream's rewritten bottom-contact
propagation) and re-added the belt-floor clip into the new propagation
loop. Gated the propagation on belt printers to prevent OOM when
belt-floor clipping produces empty initial slices.
- TriangleSelector.{cpp,hpp}: merged both new `select_patch` parameters
(HEAD's `up_direction` and upstream's `select_partially`); body uses
`dot(up_direction)` for the overhang angle check and forwards
`select_partially` to `select_triangle`.
- SupportMaterial.cpp: `slicing_params.soluble_interface` →
`zero_gap_interface_bottom` in HEAD's `detect_belt_floor_bottom_contacts`,
matching upstream's same-purpose rename at line 2495.
- Custom.json, GCodeWriter.cpp: simple additive merges (kept entries /
includes from both sides).
Verified by building OrcaSlicer (RelWithDebInfo) after a full deps
rebuild (Eigen v5.0.1, libigl v2.6.0 are now managed deps) and slicing
a scaled Benchy on the NORMALIZER belt-printer profile without OOM.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* minor logic swap
* first attempt, has a race condition
* fixed the offset issue
* found a solution, I think things work now (at least once I quash this race condition)
* still chasing down race conditions
* add manual shear / scale order strategy swap
* tweak manual shear, fix ui uninitialization crash
* fix z height / g-code desync issue
* fix shear then scale cutoff planes
* getting closer
* fix support termination planes
* fix incorrect offsets in shear-then-scale mode
* test - fix overextrusion due to model/layer scale
* Update eigen from v3.3.7 to v5.0.1.
This updates eigen from v3.3.7 released on December 11, 2018-12-11 to v5.0.1
released on 2025-11-11. There have be a large number of bug-fixes,
optimizations, and improvements between these releases. See the details at;
https://gitlab.com/libeigen/eigen/-/releases
It retains the previous custom minimal `CMakeLists.txt`, and adds a
README-OrcaSlicer.md that explains what version and parts of the upstream
eigen release have been included, and where the full release can be found.
* Update libigl from v2.0.0 (or older) to v2.6.0.
This updates libigl from what was probably v2.0.0 released on 2018-10-16 to
v2.6.0 released on 2025-05-15. It's possible the old version was even older
than that but there is no version indicators in the code and I ran out of
patience identifying missing changes and only went back as far as v2.0.0.
There have been a large number of bug-fixes, optimizations, and improvements
between these versions. See the following for details;
https://github.com/libigl/libigl/releases
I retained the minimal custom `CMakeLists.txt`, added `README.md` from the
libigl distribution which identifies the version, and added a
README-OrcaSlicer.md that details the version and parts that have been
included.
* Update libslic3r for libigl v2.6.0 changes.
This updates libslic3r for all changes moving to eigen v5.0.1 and libigl
v2.6.0. Despite the large number of updates to both dependencies, no changes
were required for the eigen update, and only one change was required for the
libigl update.
For libigl, `igl::Hit` was changed to a template taking the Scalar type to
use. Previously it was hard-coded to `float`, so to minimize possible impact
I've updated all places it is used from `igl::Hit` to `igl::Hit<float>`.
* Add compiler option `-DNOMINMAX` for libigl with MSVC.
MSVC by default defines `min(()` and `max()` macros that break
`std::numeric_limits<>::max()`. The upstream cmake that we don't include
adds `-DNOMINMAX` for the libigl module when compiling with MSVC, so we need
to add the same thing here.
* Fix src/libslic3r/TriangleMeshDeal.cpp for the unmodified upstream libigl.
This fixes `TriangleMeshDeal.cpp` to work with the unmodified upstream
libigl v2.6.0. loop.{h,cpp} implementation.
This file and feature was added in PR "BBS Port: Mesh Subdivision" (#12150)
which included changes to `loop.{h,cpp}` in the old version of libigl. This PR
avoids modifying the included dependencies, and uses the updated upstream
versions of those files without any modifications, which requires fixing
TriangleMeshDeal.cpp to work with them.
In particular, the modifications made to `loop.{h,cpp}` included changing the
return type from void to bool, adding additional validation checking of the
input meshes, and returning false if they failed validation. These added
checks looked unnecessary and would only have caught problems if the input
mesh was very corrupt.
To make `TriangleMeshDeal.cpp` work without this built-in checking
functionality, I removed checking/handling of any `false` return value.
There was also a hell of a lot of redundant copying and casting back and forth
between float and double, so I cleaned that up. The input and output meshs use
floats for the vertexes, and there would be no accuracy benefits from casting
to and from doubles for the simple weighted average operations done by
igl::loop(). So this just uses `Eigen:Map` to use the original input mesh
vertex data directly without requiring any copy or casting.
* Move eigen from included `deps_src` to externaly fetched `deps`.
This copys what PrusaSlicer did and moved it from an included dependency under
`deps_src` to an externaly fetched dependency under `deps`. This requires
updating some `CMakeList.txt` configs and removing the old and obsolete
`cmake/modules/FindEigen3.cmake`. The details of when this was done in
PrusaSlicer and the followup fixes are at;
* https://github.com/prusa3d/PrusaSlicer/commit/21116995d78b74dee69ce42874b643012a7c14e5
* https://github.com/prusa3d/PrusaSlicer/issues/13608
* https://github.com/prusa3d/PrusaSlicer/pull/13609
* https://github.com/prusa3d/PrusaSlicer/commit/e3c277b9eea0ca25e90e2378bcda198d56c4d304
For some reason I don't fully understand this also required fixing
`src/slic3r/GUI/GUI_App.cpp` by adding `#include <boost/nowide/cstdio.hpp>` to
fix an `error: ‘remove’ is not a member of ‘boost::nowide'`. The main thing I
don't understand is how it worked before. Note that this include is in the
PrusaSlicer version of this file, but it also significantly deviates from what
is currently in OrcaSlicer in many other ways.
* Whups... I missed adding the deps/Eigen/Eigen.cmake file...
* Tidy some whitespace indenting in CMakeLists.txt.
* Ugh... tabs indenting needing fixes.
* Change the include order of deps/Eigen.
It turns out that although Boost includes some references to Eigen, Eigen also
includes some references to Boost for supporting some of it's additional
numeric types.
I don't think it matters much since we are not using these features, but I
think technically its more correct to say Eigen depends on Boost than the
other way around, so I've re-ordered them.
* Add source for Eigen 5.0.1 download to flatpak yml config.
* Add explicit `DEPENDS dep_Boost to deps/Eigen.
I missed this before. This ensures we don't rely on include orders to make
sure Boost is installed before we configure Eigen.
* Add `DEPENDS dep_Boost dep_GMP dep_MPFR` to deps/Eigen.
It turns out Eigen can also use GMP and MPFR for multi-precision and
multi-precision-rounded numeric types if they are available.
Again, I don't think we are using these so it doesn't really matter, but it is
technically correct and ensures they are there if we ever do need them.
* Fix deps DEPENDENCY ordering for GMP, MPFR, Eigen, and CGAL.
I think this is finally correct. Apparently CGAL also optionally depends on
Eigen, so the correct dependency order from lowest to highest is GMP, MPFR, Eigen, and CGAL.
---------
Co-authored-by: Donovan Baarda <dbaarda@google.com>
Co-authored-by: Noisyfox <timemanager.rick@gmail.com>
Conflicts resolved in src/libslic3r/GCode.cpp and src/slic3r/GUI/GUI_Factories.cpp.
GCode.cpp: combined upstream's air-filtration per-extruder gating
(activate_air_filtration_during_print / _on_completion), the new
extrusion-role-change gcode lambda, ZAA's path.z_contoured arc-fit
disable, raft-aware slow_down_layers branch, and Vec3d/Line3 ZAA
plumbing with the local belt-printer changes (path_on_first_layer,
effective_layer_index_for_point, should_disable_arc_fitting). All
auto-merged m_writer.X() calls converted to m_writer->X() to match
the local unique_ptr<GCodeWriter> refactor.
GUI_Factories.cpp: inserted brim_flow_ratio in the Support category
list and renumbered around the local build_plate_tilt_x/y entries.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fix fan speed staying high
When fan speed-up time is enabled, layers can inherit a higher fan speed than intended.
If a layer ended with a role-driven fan change, the last applied fan speed
was not properly tracked. As a result, the next layer could start with an
incorrect fan state and keep the higher speed until another fan command
overrode it.
Ensure the emitted fan speed is always tracked correctly, including when
flushing buffered commands at the end of a layer.
* Fix: Enable instance collision detection in GCode and Print clearance
Squashed commit containing:
- Fix gcode path conflict detection in ConflictChecker.cpp by iterating all instances.
- Improve clearance validation in Print.cpp by calculating convex hulls per instance (fixes scaling/mirroring issues).
- Added // Orca: comments to mark changes.
* Fix Wipe Tower G-code conflict detection for WipeTower2
* Fix: Improve object/instance selection for collision and validation warnings
- Updated validation logic in Print.cpp to report specific ModelInstance instead of ModelObject for collision/clearance warnings.
- Updated NotificationManager and Plater to handle ModelInstance selection in 'Jump to' links.
- Added fallback to object selection if specific instance cannot be selected.
- Included fixes for G-code conflict detection (ConflictChecker, GLCanvas3D) to also report instances.
- Improved GUI_ObjectList to update canvas selection when items are selected via API.
* Fix: Prevent crash when loading .3mf projects
Moved update_selections_on_canvas() out of ObjectList::select_items() to avoid premature UI updates during loading. Canvas updates are now explicitly called in NotificationManager and Plater callbacks where needed.
* Fix: Address code review comments
- Fix memory allocation for extrusion layers deep copy
- Remove unused variable in GLCanvas3D
- Fix string formatting crash risk in NotificationManager
- Remove dead code in Plater
---------
Co-authored-by: SoftFever <softfeverever@gmail.com>
- Add BeltBackTransform class that inverts the shear/scale matrix and
applies it in GCodeWriter::to_machine_coords() so G-code outputs in
the machine's physical coordinate space, gated by new
belt_gcode_back_transform config option
- Extend belt floor clipping to all three tree support pipelines
(Prusa-style, Orca organic, TreeModelVolumes) with per-layer polygon
clipping, anti-overhang integration, and belt raft extension layers
- Fix tree drop_nodes() belt termination, organic support global Z
offset, collision calculation index bug, and first-layer brim/empty
layer checks for belt printers
two-shot - first build built but didn't plumb to UI. Woah.
add pre-slice axis remap, because Y needs to be Z
going to change tactic and move based on bbox min
switch to per axis snapping
per axis swap snap now per object
build plate tilt wasn't invalidating slicer settings
support upper bound now correct, need to get lower bound corrected
axis swapped support termination corrected
Z Shear works with and without pre-slice remap now
- Fix support clipping z-shift calculation by removing coordinate-space
mismatch and sync belt_floor_z_shift with global_z_offset; fix
invalidation so posSupportMaterial no longer resets slicing params
- Add belt floor polygon clipping to non-organic tree support
(slim/strong/hybrid) with collision surface integration in
TreeSupportData, belt extension layers, and first-layer brim
suppression
- Add belt floor clipping to organic tree support pipeline with virtual
belt raft layers, per-layer polygons in TreeModelVolumes, and
post-generation layer trimming; fix pre-existing processing_last_mesh
bug in calculateCollision()
Fix belt floor support clipping: z-shift, invalidation, and global offset
- Fix support clipping z-shift calculation by removing coordinate-space
mismatch (raw_bounding_box min.z vs trafo_centered m_belt_min_z) and
sync belt_floor_z_shift with global_z_offset in global shear mode
- Fix invalidation so posSupportMaterial no longer resets slicing params,
preventing the exact posSlice z-shift from being overwritten by the
bounding-box approximation on support-only setting changes
- Remove double-counting of global z_offset on support layers — support
already inherits the offset from object layers during generation
This Work Was Co-Authored-By Claude Opus 4.6 (1M context) <noreply@anthropic.com>
UI: gray out inactive belt sub-options, rename to mesh transforms, move to Advanced
Fix mesh clipping through build plate after belt shear/scale transform
Generalize G-code viewer designed-view toggle for full belt transform
Clip support layers to transformed belt floor plane
Supports below the tilted build plate (Z = shear_factor * from_axis - min_z)
are now clipped via half-plane intersection after generation. Belt floor
parameters stored in SlicingParameters and populated in both update_slicing_parameters()
and the static slicing_parameters() overload.
Make belt G-code viewer toggle more prominent, add B keyboard shortcut
- Add separator + teal "Belt Printer" header in legend panel
- Append [B] hint to checkbox label
- Add B key shortcut in GLCanvas3D to toggle designed/machine view
- Read belt_printer_angle from loaded G-code headers to enable belt view
Add per-axis global transform option for belt printer shear
New belt_shear_{x,y,z}_global bool configs. When enabled, shear incorporates
instance shift so objects at different bed positions get position-aware
transform (Z += factor * instance_shift_on_from_axis).
Fix global shear: use layer Z offset instead of mesh transform, add config invalidation
- Global shear offset applied as post-slicing layer print_z adjustment
instead of mesh transform (which was absorbed by min_z normalization
or shifted mesh out of slice range)
- Register all belt transform options in Print::invalidate_state_by_config_options
to trigger posSlice re-slicing (the fallback only invalidated Print steps,
not PrintObject steps — belt changes had no effect without manual re-slice)
- Belt gcode remap options added to steps_gcode (gcode-export only)
- Skip empty-first-layer check for belt objects with global Z offset
WIP: split instances for global shear, relative Z offsets, debug logging
- PrintApply: when belt global mode active, prevent instance grouping by
adding unique Z perturbation to trafo — each copy becomes its own
PrintObject with independent layers
- PrintObjectSlice: compute global Z offset relative to minimum Y shift
across all PrintObjects (lowest-Y object stays at Z=0)
- Debug logging (warning level) for belt global shift values and offsets
Known issues:
- Cached posSlice results cause stale offsets when mixing copies with
individually-added objects — need to compute min baseline outside slice()
- Supports still generate to Z=0 instead of object's global Z offset
Fix global shear for copied objects: disable shared-object layer optimization
When belt global Z shear is active, each object needs unique layer Z
values based on its bed position. The shared-object optimization was
causing copies to reuse the source object's layers (and its Z offset)
instead of computing their own position-based offset.
started work on getting supports to work properly
one step forward, one step back
this version didn't quite work. Getting somewhere though
about to add UI controllable tests
added configuration options for supports
tweak CLAUDE.md to be more aggressive for my machine. This commit should probably be pulled out before contributing upstream
still chasing down some bugs
moving objects between slices no longer results in improper Z-height because of caching
added more data to the debug logs
Z offset is getting more global again
still not quite there, I think there's a fundamental logic flaw?
hunting for bugs
finally have a functional fix
Add belt floor clipping to tree supports (organic and non-organic)
- Add belt floor polygon clipping to non-organic tree support
(slim/strong/hybrid) in draw_circles() and terminate nodes at the
belt surface instead of the horizontal build plate
- Add belt floor clipping to organic tree support pipeline with virtual
belt raft layers for sub-floor branch generation, per-layer belt
floor polygons in TreeModelVolumes, and post-generation layer trimming
- Fix pre-existing processing_last_mesh bug in TreeModelVolumes that
prevented m_anti_overhang (support blockers) from ever being applied;
skip empty first layer check for belt printers
Commits:
current approach: make a face surface to build supports to
closer!
supports now terminate on shear plane, now need to get shear plane to correct Z height
nearly there
chasing down logic issues still
committing for checkpoint, this still does not work
still got logic problems...
cull support clipping
stashing changes for now. Going to focus on getting the global shear OFF support generation dialed first.
beginning per object shear calcs
Local shear transform is on correct Z offset now
local shear finally works now and needs more testing
global shear works now, needs thorough testing
debugging non-45 degree angles
debugging part 2
supports at all angles work now
remove debug logging
Add belt floor collision to non-organic tree support pipeline
- Integrate belt floor as a collision surface in TreeSupportData so
branches route around the belt naturally, replacing the explicit
termination checks in drop_nodes()
- Add belt extension layers below the object after draw_circles() to
allow support geometry to extend to the diagonal belt surface instead
of terminating at a horizontal first layer
- Fix coordinate overflow in belt floor polygons (scale_(1e4) exceeds
int32), skip first-layer brim expansion for belt printers, and
extend empty first layer check bypass to all belt modes
add debug logging, Z translate for tree supports
still not seeing any cutoff surface yet
adding debug options
attempt #2 at trees
if hit Z buildplate stop but don't set to_buildplate true
getting closer
tree support almost there, just need to get rid of the circles at the beginning
getting closer
belt / shear plane clip works, need to figure out the buidlplate plane issues
more logic, added debugging logs
supports now extend somewhat below Z=0 in global shear mode
fix bad alloc, add 10mm below build plate
fully works now
shear transform + prusa tree support generation works now.
pull out debug logging
- Implement per-object global shear transform in PrintObject with
layer Z-offset calculation, config invalidation, and fix for
shared-object layer optimization breaking copied objects
- Clip support layers to the transformed belt floor plane and begin
work on tree support adaptation for sheared coordinate space
- Improve belt UI: gray out inactive sub-options, add B keyboard
shortcut for G-code viewer design-view toggle, fix mesh clipping
through build plate after shear/scale transform
y' = y + z·cot(α),
while x' = x and z' = z
getting closer to customizable variant
getting closer
X/Y/Z shear initial
clean up UI
add 1/sin(a) transform, idea taken from blackbelt cura plugin
Things work now (turns out I've been using the wrong set of transforms)
- 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.
- Implement core belt slicing pipeline: R(-alpha, X) mesh rotation in PrintObjectSlice with corrected object height calculation for proper layer count
Add to_machine_coords() in GCodeWriter to convert slicing-frame coordinates back to machine-frame, propagated through GCode,
GCodeProcessor, and GCodeViewer
Add belt-mode UI: tilted bed visualization, slicing-direction arrow, and raw G-code toggle to switch between machine-frame and slicing-frame views
This is a combination of 6 commits.
checkpoint 1: initial MVP. Slicing functions, but rotates instead of skews are happening and a lot of other stuff too
getting somewhere, getting to the point where I need to figure out how to verify this stuff
this appears to be a dead end.
getting somewhere I think maybe
I'm pretty sure we've completely lost the plot at this point and need to restart this process...
remove slice logic in preparation for new, more invasive plan
- Handle z contouring in variable speed flow when emitting GCode
- Add logic to restore nominnal z height for regular extrusions
- preserve z_contoured flag when splitting extrusion paths
Previously, wipe tower behavior was determined by checking if the printer
was a QIDI vendor. This introduces a configurable enum (Type 1 / Type 2)
so any printer can select its wipe tower implementation. BBL printers
remain hardcoded to Type 1. Qidi profiles default to Type 1.