From 501aff7e53871d2de3fa3d037e68ae8fcef1c680 Mon Sep 17 00:00:00 2001 From: harrierpigeon Date: Thu, 12 Mar 2026 14:25:30 -0500 Subject: [PATCH] Part 2: Replace belt rotation w/ per-axis shear transforms and G-code axis remap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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. --- src/libslic3r/GCode.cpp | 27 ++++++++- src/libslic3r/GCode/GCodeProcessor.cpp | 9 ++- src/libslic3r/GCode/GCodeProcessor.hpp | 3 +- src/libslic3r/GCodeWriter.cpp | 16 +++++- src/libslic3r/GCodeWriter.hpp | 7 ++- src/libslic3r/PrintObject.cpp | 19 +++++-- src/libslic3r/PrintObjectSlice.cpp | 20 ++++++- src/slic3r/GUI/3DBed.cpp | 79 ++++++++++++++++++++++++-- src/slic3r/GUI/3DBed.hpp | 2 + src/slic3r/GUI/GCodeViewer.cpp | 20 ++++++- src/slic3r/GUI/GCodeViewer.hpp | 2 + 11 files changed, 183 insertions(+), 21 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 7b881ea74f..dd9e477149 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -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::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::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 diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 6c5c837b92..eddfc56440 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -2597,8 +2597,6 @@ void GCodeProcessor::finalize(bool post_process) } } - // Belt printer: preview coordinate transform placeholder (to be implemented in next cycle). - calculate_time(m_result); // process the time blocks @@ -3053,6 +3051,13 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers } catch (...) {} return; } + // Belt printer Z-shift for raw G-code toggle in preview. + if (boost::starts_with(comment, " belt_z_shift = ")) { + try { + m_result.belt_z_shift = std::stof(std::string(comment.substr(16))); + } catch (...) {} + return; + } // wipe start tag if (boost::starts_with(comment, reserved_tag(ETags::Wipe_Start))) { diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index e432a165a8..af68a5a6b7 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -227,8 +227,9 @@ class Print; bool support_traditional_timelapse{true}; float printable_height; float z_offset; - // Belt printer: angle for coordinate transformation in preview. + // Belt printer: angle and Z-shift for coordinate transformation in preview. float belt_printer_angle{ 0.f }; + float belt_z_shift{ 0.f }; SettingsIds settings_ids; size_t filaments_count; bool backtrace_enabled; diff --git a/src/libslic3r/GCodeWriter.cpp b/src/libslic3r/GCodeWriter.cpp index 7d4ac3babb..bb606b222e 100644 --- a/src/libslic3r/GCodeWriter.cpp +++ b/src/libslic3r/GCodeWriter.cpp @@ -29,8 +29,20 @@ void GCodeWriter::set_belt_angle(double angle_deg) Vec3d GCodeWriter::to_machine_coords(const Vec3d &pos) const { - // Belt printer: coordinate transform placeholder (to be implemented in next cycle). - return pos; + if (!is_belt_printer()) + return pos; + + // Undo the slicing transform to recover machine-frame coordinates. + // Slicing applied: T(0,0,-min_z_rot) * R(-alpha, X) * original_pos + // Inverse: R(+alpha, X) * T(0,0,+min_z_rot) * slicing_pos + // + // First undo the Z-shift, then apply R(+alpha, X). + double sz = pos.z() + m_belt_z_shift; // undo T(0,0,-min_z_rot) + return Vec3d( + pos.x(), + pos.y() * m_belt_cos - sz * m_belt_sin, // R(+alpha, X) + pos.y() * m_belt_sin + sz * m_belt_cos + ); } bool GCodeWriter::supports_separate_travel_acceleration(GCodeFlavor flavor) diff --git a/src/libslic3r/GCodeWriter.hpp b/src/libslic3r/GCodeWriter.hpp index 10159d941f..f9b5ed79ac 100644 --- a/src/libslic3r/GCodeWriter.hpp +++ b/src/libslic3r/GCodeWriter.hpp @@ -127,8 +127,10 @@ public: // Belt printer: set the belt angle and precompute sin/cos for coordinate transformation. void set_belt_angle(double angle_deg); + void set_belt_z_shift(double z_shift) { m_belt_z_shift = z_shift; } + double belt_z_shift() const { return m_belt_z_shift; } bool is_belt_printer() const { return m_belt_angle_rad != 0.; } - // Transform a point from the slicing frame to machine/world coordinates (inverse shear). + // Transform a point from the slicing frame to machine/world coordinates (inverse rotation). Vec3d to_machine_coords(const Vec3d &pos) const; // Returns whether this flavor supports separate print and travel acceleration. @@ -184,10 +186,11 @@ public: //SoftFever bool m_is_bbl_printers = false; - // Belt printer coordinate transformation (YZ shear) + // Belt printer coordinate transformation (inverse of slicing rotation) double m_belt_angle_rad = 0.; double m_belt_cos = 1.0; double m_belt_sin = 0.0; + double m_belt_z_shift = 0.; // Z-shift applied during slicing (min_z_rotated, typically negative) double m_current_speed; bool m_is_first_layer = true; diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 979953fb94..08ff847951 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -3392,7 +3392,13 @@ void PrintObject::update_slicing_parameters() // Orca: updated function call for XYZ shrinkage compensation if (!m_slicing_params.valid) { coordf_t object_height = this->model_object()->max_z(); - // Belt printer: height adjustment placeholder (to be implemented in next cycle). + if (this->print()->config().belt_printer.value) { + // After mesh rotation R(-alpha, X), effective height in the slicing + // direction is y_extent*sin(a) + z_extent*cos(a). + double angle_rad = Geometry::deg2rad(this->print()->config().belt_printer_angle.value); + BoundingBoxf3 bb = this->model_object()->raw_bounding_box(); + object_height = bb.size().y() * std::sin(angle_rad) + bb.size().z() * std::cos(angle_rad); + } m_slicing_params = SlicingParameters::create_from_config(this->print()->config(), m_config, object_height, this->object_extruders(), this->print()->shrinkage_compensation()); } @@ -3432,9 +3438,14 @@ SlicingParameters PrintObject::slicing_parameters(const DynamicPrintConfig &full sort_remove_duplicates(object_extruders); //FIXME add painting extruders - if (object_max_z <= 0.f) - object_max_z = (float)model_object.raw_bounding_box().size().z(); - // Belt printer: height adjustment placeholder (to be implemented in next cycle). + if (object_max_z <= 0.f) { + BoundingBoxf3 bb = model_object.raw_bounding_box(); + object_max_z = (float)bb.size().z(); + if (print_config.belt_printer.value) { + double angle_rad = Geometry::deg2rad(print_config.belt_printer_angle.value); + object_max_z = (float)(bb.size().y() * std::sin(angle_rad) + bb.size().z() * std::cos(angle_rad)); + } + } return SlicingParameters::create_from_config(print_config, object_config, object_max_z, object_extruders, object_shrinkage_compensation); } diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp index bba4593764..2748151aa0 100644 --- a/src/libslic3r/PrintObjectSlice.cpp +++ b/src/libslic3r/PrintObjectSlice.cpp @@ -140,7 +140,25 @@ static std::vector slice_volumes_inner( params_base.closing_radius = print_object_config.slice_closing_radius.value; params_base.extra_offset = 0; params_base.trafo = object_trafo; - // Belt printer: mesh transform placeholder (to be implemented in next cycle). + if (print_config.belt_printer.value) { + double angle_rad = Geometry::deg2rad(print_config.belt_printer_angle.value); + // Rotate mesh by -alpha about X so horizontal slice planes = gantry-parallel planes. + // The gantry (XY) is tilted by belt_printer_angle; this rotation aligns it with horizontal. + Transform3d belt_rotation = Transform3d::Identity(); + belt_rotation.rotate(Eigen::AngleAxisd(-angle_rad, Vec3d::UnitX())); + params_base.trafo = belt_rotation * params_base.trafo; + // Compute Z-shift from model_volumes: find min-Z of all rotated meshes + // so the rotated geometry starts at Z=0 (the belt surface in slicing frame). + double min_z_rotated = std::numeric_limits::max(); + for (const ModelVolume *mv : model_volumes) { + if (!model_volume_needs_slicing(*mv)) continue; + BoundingBoxf3 bb = mv->mesh().bounding_box(); + bb = bb.transformed(params_base.trafo * mv->get_matrix()); + min_z_rotated = std::min(min_z_rotated, bb.min.z()); + } + if (min_z_rotated != std::numeric_limits::max() && std::abs(min_z_rotated) > EPSILON) + params_base.trafo = Eigen::Translation3d(0, 0, -min_z_rotated) * params_base.trafo; + } //BBS: 0.0025mm is safe enough to simplify the data to speed slicing up for high-resolution model. //Also has on influence on arc fitting which has default resolution 0.0125mm. params_base.resolution = print_config.resolution <= 0.001 ? 0.0f : 0.0025; diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 101279d744..858182946c 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -387,17 +387,18 @@ void Bed3D::render_internal(GLCanvas3D& canvas, const Transform3d& view_matrix, m_model.set_color(m_is_dark ? DEFAULT_MODEL_COLOR_DARK : DEFAULT_MODEL_COLOR); - // Belt printer: bed view transform placeholder (to be implemented in next cycle). - Transform3d belt_view_matrix = view_matrix; + // Belt printer: bed rotation is applied inside render_model() and render_default() + // using m_is_belt_printer and m_belt_angle members. switch (m_type) { - case Type::System: { render_system(canvas, belt_view_matrix, projection_matrix, bottom); break; } + case Type::System: { render_system(canvas, view_matrix, projection_matrix, bottom); break; } default: - case Type::Custom: { render_custom(canvas, belt_view_matrix, projection_matrix, bottom); break; } + case Type::Custom: { render_custom(canvas, view_matrix, projection_matrix, bottom); break; } } render_gravity_arrow(view_matrix, projection_matrix); + render_slicing_arrow(view_matrix, projection_matrix); render_slicing_plane(view_matrix, projection_matrix); glsafe(::glDisable(GL_DEPTH_TEST)); @@ -698,7 +699,13 @@ void Bed3D::render_model(const Transform3d& view_matrix, const Transform3d& proj if (shader != nullptr) { shader->start_using(); shader->set_uniform("emission_factor", 0.0f); - const Transform3d model_matrix = Geometry::assemble_transform(m_model_offset); + Transform3d model_matrix = Geometry::assemble_transform(m_model_offset); + // Belt printer: rotate the bed model about X so the belt tilt is visible. + // Negative angle: belt surface tilts downward away from the nozzle. + if (m_is_belt_printer && m_belt_angle > 0.f) { + double angle_rad = Geometry::deg2rad(static_cast(m_belt_angle)); + model_matrix = Eigen::AngleAxisd(-angle_rad, Vec3d::UnitX()) * model_matrix; + } shader->set_uniform("volume_world_matrix", model_matrix); shader->set_uniform("view_model_matrix", view_matrix * model_matrix); shader->set_uniform("projection_matrix", projection_matrix); @@ -798,6 +805,58 @@ void Bed3D::render_gravity_arrow(const Transform3d& view_matrix, const Transform shader->stop_using(); } +void Bed3D::render_slicing_arrow(const Transform3d& view_matrix, const Transform3d& projection_matrix) +{ + if (!m_is_belt_printer || m_belt_angle <= 0.f) + return; + + // Build the arrow model: shorter and wider than the gravity arrow. + if (!m_slicing_arrow.is_initialized()) { + const float stem_length = 15.0f; // shorter than gravity arrow (25) + const float stem_radius = 1.0f; // wider than gravity arrow (~0.33) + const float tip_radius = 3.0f; // wider tip + const float tip_length = 5.0f; + m_slicing_arrow.init_from(stilized_arrow(16, tip_radius, tip_length, stem_radius, stem_length)); + } + + // The slicing direction: layers stack along the gantry normal. + // With mesh rotation R(-alpha, X), the slicing Z-axis in the original frame + // points in direction R(+alpha, X) * (0, 0, 1) = (0, -sin(alpha), cos(alpha)). + double angle_rad = Geometry::deg2rad(static_cast(m_belt_angle)); + Vec3d slice_dir = Vec3d(0., -std::sin(angle_rad), std::cos(angle_rad)).normalized(); + + // Compute rotation to align +Z (arrow default) with slice_dir. + Vec3d from = Vec3d::UnitZ(); + double dot = from.dot(slice_dir); + Transform3d rot = Transform3d::Identity(); + if (dot < -0.9999) { + rot = Eigen::AngleAxisd(M_PI, Vec3d::UnitX()) * rot; + } else if (dot < 0.9999) { + Vec3d axis = from.cross(slice_dir).normalized(); + double angle = std::acos(std::clamp(dot, -1.0, 1.0)); + rot = Eigen::AngleAxisd(angle, axis) * rot; + } + + GLShaderProgram* shader = wxGetApp().get_shader("flat"); + if (shader == nullptr) + return; + + // Disable depth test so the arrow is always visible (not occluded by the tilted bed). + glsafe(::glDisable(GL_DEPTH_TEST)); + shader->start_using(); + + const Camera& camera = wxGetApp().plater()->get_camera(); + Transform3d model_matrix = rot; + shader->set_uniform("view_model_matrix", camera.get_view_matrix() * model_matrix); + shader->set_uniform("projection_matrix", camera.get_projection_matrix()); + + m_slicing_arrow.set_color({ 1.0f, 0.2f, 0.6f, 1.0f }); // pink + m_slicing_arrow.render(); + + shader->stop_using(); + glsafe(::glEnable(GL_DEPTH_TEST)); +} + void Bed3D::render_slicing_plane(const Transform3d& view_matrix, const Transform3d& projection_matrix) { if (!m_is_belt_printer || m_belt_angle <= 0.f) @@ -863,7 +922,15 @@ void Bed3D::render_default(bool bottom, const Transform3d& view_matrix, const Tr if (shader != nullptr) { shader->start_using(); - shader->set_uniform("view_model_matrix", view_matrix); + // Belt printer: rotate the default bed about X so the belt tilt is visible. + Transform3d view_model_matrix = view_matrix; + if (m_is_belt_printer && m_belt_angle > 0.f) { + double angle_rad = Geometry::deg2rad(static_cast(m_belt_angle)); + Transform3d belt_rotation = Transform3d::Identity(); + belt_rotation.rotate(Eigen::AngleAxisd(-angle_rad, Vec3d::UnitX())); + view_model_matrix = view_matrix * belt_rotation; + } + shader->set_uniform("view_model_matrix", view_model_matrix); shader->set_uniform("projection_matrix", projection_matrix); glsafe(::glEnable(GL_DEPTH_TEST)); diff --git a/src/slic3r/GUI/3DBed.hpp b/src/slic3r/GUI/3DBed.hpp index 005dbff534..d01273961d 100644 --- a/src/slic3r/GUI/3DBed.hpp +++ b/src/slic3r/GUI/3DBed.hpp @@ -111,6 +111,7 @@ private: GLModel m_model; Vec3d m_model_offset{ Vec3d::Zero() }; GLModel m_gravity_arrow; + GLModel m_slicing_arrow; // Pink arrow showing the effective slicing direction GLModel m_slicing_plane; // Debug: shows the intended slicing plane direction Axes m_axes; @@ -189,6 +190,7 @@ private: void render_custom(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom); void render_default(bool bottom, const Transform3d& view_matrix, const Transform3d& projection_matrix); void render_gravity_arrow(const Transform3d& view_matrix, const Transform3d& projection_matrix); + void render_slicing_arrow(const Transform3d& view_matrix, const Transform3d& projection_matrix); void render_slicing_plane(const Transform3d& view_matrix, const Transform3d& projection_matrix); // BBS: remove the bed picking logic diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 7df0b06ff5..dd66c918a7 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -1271,6 +1271,7 @@ void GCodeViewer::load_as_gcode(const GCodeProcessorResult& gcode_result, const m_max_print_height = gcode_result.printable_height; m_z_offset = gcode_result.z_offset; + m_belt_z_shift = gcode_result.belt_z_shift; // load_toolpaths(gcode_result, build_volume, exclude_bounding_box); @@ -2209,7 +2210,16 @@ void GCodeViewer::render_toolpaths() { const Camera& camera = wxGetApp().plater()->get_camera(); Matrix4f view = camera.get_view_matrix().matrix().cast(); - // Belt view: view matrix transform placeholder (to be implemented in next cycle). + // Belt "raw" view: apply slicing rotation to view matrix so toolpaths appear + // in the slicing frame (rotated part with horizontal layers). + if (m_belt_show_raw && m_belt_view_enabled && m_belt_angle_deg > 0.f) { + double angle_rad = Geometry::deg2rad(static_cast(m_belt_angle_deg)); + // Apply R(-alpha, X) * T(0,0,-z_shift) to bring machine coords back to slicing frame. + Transform3d slicing_trafo = Transform3d::Identity(); + slicing_trafo.translate(Vec3d(0., 0., -static_cast(m_belt_z_shift))); + slicing_trafo = Eigen::AngleAxisd(-angle_rad, Vec3d::UnitX()) * slicing_trafo; + view = (camera.get_view_matrix() * slicing_trafo).matrix().cast(); + } const libvgcode::Mat4x4 converted_view_matrix = libvgcode::convert(view); const libvgcode::Mat4x4 converted_projetion_matrix = libvgcode::convert(static_cast(camera.get_projection_matrix().matrix().cast())); #if VGCODE_ENABLE_COG_AND_TOOL_MARKERS @@ -4406,6 +4416,14 @@ void GCodeViewer::render_legend(float &legend_height, int canvas_width, int canv if (m_nozzle_nums > 1 && (m_viewer.get_view_type() == libvgcode::EViewType::Summary || m_viewer.get_view_type() == libvgcode::EViewType::ColorPrint)) // ORCA show only on summary and filament tab render_legend_color_arr_recommen(window_padding); + // Belt printer: toggle for viewing raw slicing-frame G-code + if (m_belt_view_enabled) { + ImGui::Spacing(); + ImGui::Dummy({ window_padding, 0 }); + ImGui::SameLine(); + ImGui::Checkbox("Show raw G-code (slicing frame)", &m_belt_show_raw); + } + legend_height = ImGui::GetCurrentWindow()->Size.y; imgui.end(); ImGui::PopStyleColor(7); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index a299b93058..4bd3746991 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -239,6 +239,8 @@ mutable bool m_no_render_path { false }; bool m_belt_view_enabled = false; float m_belt_angle_deg = 0.f; + float m_belt_z_shift = 0.f; + bool m_belt_show_raw = false; // Toggle: show raw slicing-frame G-code (rotated part) libvgcode::Viewer m_viewer; bool m_loaded_as_preview{ false };