mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-15 23:12:08 +00:00
belt: anchor the designed-view G-code preview onto the model bounding box
The belt designed (upright) preview back-transforms the machine-frame G-code into model space with the linear belt inverse. That inverse recovers the print's shape and orientation, but not the per-object placement/lift translation: the object's position on the belt, the BeltSliceStrategy min-Z lift, and the centering pre-translate are applied OUTSIDE build_forward_transform() (see PrintObjectSlice.cpp), so its linear inverse cannot undo them. The result was a constant offset (~20 mm on the belt-advance axis) of the toolpaths from the model shell, on every model. Recover the missing translation generally — independent of the offset's exact source or the axis remap — by anchoring the back-transformed object body (extrusions on layer_id >= 1, i.e. excluding the layer-0 prime/skirt) onto the upright model bounding box, the same space the shells render in, and folding that translation into the belt inverse before converting to libvgcode. Replaces the previous Y=0 anchoring in LibVGCodeWrapper, which pinned the toolpaths to the belt entry rather than to the model and so left the offset in place for any object not sitting at the origin.
This commit is contained in:
@@ -1229,10 +1229,36 @@ void GCodeViewer::load_as_gcode(const GCodeProcessorResult& gcode_result, const
|
||||
// inverse (handles any mesh rotation + shear + axis remap). When off, the raw
|
||||
// machine-frame G-code is shown (useful for debugging the transform itself).
|
||||
const bool is_belt = print.config().belt_printer.value;
|
||||
const Transform3d belt_inv = (is_belt && m_belt_show_designed)
|
||||
Transform3d belt_inv = (is_belt && m_belt_show_designed)
|
||||
? compute_belt_back_transform(print.config()) : Transform3d::Identity();
|
||||
const bool apply_belt = is_belt && m_belt_show_designed
|
||||
&& !belt_inv.matrix().isApprox(Transform3d::Identity().matrix());
|
||||
if (apply_belt) {
|
||||
// The linear belt back-transform recovers the print's shape and orientation but not
|
||||
// the per-object placement/lift translation: the object's position on the belt, the
|
||||
// BeltSliceStrategy min-Z lift, and the centering pre-translate are applied OUTSIDE
|
||||
// build_forward_transform() (see PrintObjectSlice.cpp), so its linear inverse leaves
|
||||
// them un-undone. Uncorrected, the upright toolpaths float a fixed offset from the
|
||||
// model shell. Recover the translation generally — independent of the offset's exact
|
||||
// source or the axis remap — by anchoring the back-transformed object body onto the
|
||||
// upright model bounding box (the same space the shells render in).
|
||||
BoundingBoxf3 model_bb;
|
||||
for (const PrintObject* po : print.objects())
|
||||
for (const ModelInstance* mi : po->model_object()->instances)
|
||||
model_bb.merge(po->model_object()->instance_bounding_box(*mi));
|
||||
BoundingBoxf3 tp_bb;
|
||||
for (const GCodeProcessorResult::MoveVertex& mv : gcode_result.moves)
|
||||
if (mv.type == EMoveType::Extrude && mv.layer_id >= 1) // skip layer-0 prime/skirt
|
||||
tp_bb.merge(Vec3d(belt_inv * mv.position.cast<double>()));
|
||||
if (model_bb.defined && tp_bb.defined) {
|
||||
const Vec3d d = model_bb.min - tp_bb.min;
|
||||
belt_inv = Transform3d(Eigen::Translation3d(d)) * belt_inv;
|
||||
BOOST_LOG_TRIVIAL(debug) << "[BELT-PREVIEW] anchor: model_bb.min=("
|
||||
<< model_bb.min.x() << "," << model_bb.min.y() << "," << model_bb.min.z()
|
||||
<< ") tp_bb.min=(" << tp_bb.min.x() << "," << tp_bb.min.y() << "," << tp_bb.min.z()
|
||||
<< ") d=(" << d.x() << "," << d.y() << "," << d.z() << ")";
|
||||
}
|
||||
}
|
||||
libvgcode::GCodeInputData data = libvgcode::convert(gcode_result, str_tool_colors, str_color_print_colors, m_viewer,
|
||||
apply_belt ? &belt_inv : nullptr);
|
||||
|
||||
|
||||
@@ -275,25 +275,10 @@ GCodeInputData convert(const Slic3r::GCodeProcessorResult& result, const std::ve
|
||||
}
|
||||
ret.vertices.shrink_to_fit();
|
||||
|
||||
// Belt designed view: the linear back-transform recovers the correct shape
|
||||
// and orientation, but not the constant machine-frame origin offset baked
|
||||
// into the G-code (e.g. the start-G-code belt advance + a G92 reset leaves a
|
||||
// ~20 mm Z residual). Anchor the lowest extrusion to the belt entry (Y=0) so
|
||||
// the toolpaths sit on the bed under the model shell. Independent of the
|
||||
// offset's source, so it stays general across machines.
|
||||
if (belt_xform != nullptr && !ret.vertices.empty()) {
|
||||
// Anchor on the OBJECT extrusions only (layer_id >= 1): the start-G-code
|
||||
// prime lines (layer 0) print at the belt origin, while the object prints
|
||||
// after the start-G-code belt advance, so anchoring on the global min
|
||||
// would lock onto the prime and leave the object offset.
|
||||
float min_y = std::numeric_limits<float>::max();
|
||||
for (const PathVertex& v : ret.vertices)
|
||||
if (v.type == EMoveType::Extrude && v.layer_id >= 1 && v.position[1] < min_y)
|
||||
min_y = v.position[1];
|
||||
if (min_y != std::numeric_limits<float>::max() && std::abs(min_y) > 1e-3f)
|
||||
for (PathVertex& v : ret.vertices)
|
||||
v.position[1] -= min_y;
|
||||
}
|
||||
// Note: the belt designed-view anchoring (recovering the per-object placement/
|
||||
// lift translation the linear back-transform cannot) is folded into belt_xform
|
||||
// by the caller (GCodeViewer::load_as_gcode), which anchors onto the upright
|
||||
// model bounding box. Nothing extra to do here.
|
||||
|
||||
ret.spiral_vase_mode = result.spiral_vase_mode;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user