From d0c068a2306bc648fb3b5479f58f03b682f0fdc7 Mon Sep 17 00:00:00 2001 From: Hanif Koh Date: Sun, 13 Sep 2026 16:28:09 +0800 Subject: [PATCH] Apply the Belt Slicing Transform to Painted Supports and Seams Painted support/seam facets, support volumes, seam occlusion, MMU top/bottom painting and the adaptive infill octree used trafo_centered() while the layers were sliced with the belt rotation, remap and Z lift; they now share PrintObject::trafo_sliced(). --- src/libslic3r/GCode/SeamPlacer.cpp | 4 ++-- src/libslic3r/MultiMaterialSegmentation.cpp | 2 +- src/libslic3r/Print.hpp | 3 +++ src/libslic3r/PrintObject.cpp | 10 +++++++--- src/libslic3r/PrintObjectSlice.cpp | 9 ++++++++- 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 35bc436d5a..7562c7745d 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -627,7 +627,7 @@ void compute_global_occlusion(GlobalModelInfo &result, const PrintObject *po, SeamPosition seam_position = spAligned) { BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: gather occlusion meshes: start"; - auto obj_transform = po->trafo_centered(); + auto obj_transform = po->trafo_sliced(); indexed_triangle_set triangle_set; indexed_triangle_set negative_volumes_set; //add all parts @@ -712,7 +712,7 @@ void gather_enforcers_blockers(GlobalModelInfo &result, const PrintObject *po) { BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: build AABB trees for raycasting enforcers/blockers: start"; - auto obj_transform = po->trafo_centered(); + auto obj_transform = po->trafo_sliced(); for (const ModelVolume *mv : po->model_object()->volumes) { if (mv->is_seam_painted()) { diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index 6f80f7b759..33b7520568 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -1215,7 +1215,7 @@ static inline std::vector> segmentation_top_and_bottom_l // project downards pointing painted triangles over bottom surfaces. std::vector> top_raw(num_facets_states), bottom_raw(num_facets_states); std::vector zs = zs_from_layers(layers); - Transform3d object_trafo = print_object.trafo_centered(); + Transform3d object_trafo = print_object.trafo_sliced(); #ifdef MM_SEGMENTATION_DEBUG_TOP_BOTTOM static int iRun = 0; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index f3da337bb7..bc1a541197 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -359,6 +359,9 @@ public: // Trafo with the center_offset() applied after the transformation, to center the object in XY before slicing. Transform3d trafo_centered() const { Transform3d t = this->trafo(); t.pretranslate(Vec3d(- unscale(m_center_offset.x()), - unscale(m_center_offset.y()), 0)); return t; } + // trafo_centered() with the belt pre-slice transforms applied: the frame the layers were sliced in (Layer::slice_z). + // Equal to trafo_centered() unless a belt rotation or pre-slice remap is active. + Transform3d trafo_sliced() const; const PrintInstances& instances() const { return m_instances; } PrintInstances &instances() { return m_instances; } diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 6d9bfba090..bbbee454b3 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1072,7 +1072,10 @@ std::pair PrintObject::prepare indexed_triangle_set mesh = this->model_object()->raw_indexed_triangle_set(); // Rotate mesh and build octree on it with axis-aligned (standart base) cubes. auto to_octree = transform_to_octree().toRotationMatrix(); - its_transform(mesh, to_octree * this->trafo_centered(), true); + // Overhangs below are placed at Layer::bottom_z(), which includes the belt global Z offset. + Transform3d object_trafo = this->trafo_sliced(); + object_trafo.translation().z() += m_belt_global_z_offset; + its_transform(mesh, to_octree * object_trafo, true); // Triangulate internal bridging surfaces. std::vector> overhangs(std::max(surfaces_w_bottom_z.size(), size_t(1))); @@ -5058,6 +5061,7 @@ static void project_triangles_to_slabs(ConstLayerPtrsAdaptor layers, const index void PrintObject::project_and_append_custom_facets( bool seam, EnforcerBlockerType type, std::vector& out, std::vector>* vertical_points) const { + const Transform3d object_trafo = this->trafo_sliced(); for (const ModelVolume* mv : this->model_object()->volumes) if (mv->is_model_part()) { const indexed_triangle_set custom_facets = seam @@ -5066,12 +5070,12 @@ void PrintObject::project_and_append_custom_facets( if (! custom_facets.indices.empty()) { if (seam) project_triangles_to_slabs(this->layers(), custom_facets, - (this->trafo_centered() * mv->get_matrix()).cast(), + (object_trafo * mv->get_matrix()).cast(), seam, out); else { std::vector projected; // Support blockers or enforcers. Project downward facing painted areas upwards to their respective slicing plane. - slice_mesh_slabs(custom_facets, zs_from_layers(this->layers()), this->trafo_centered() * mv->get_matrix(), nullptr, &projected, vertical_points, [](){}); + slice_mesh_slabs(custom_facets, zs_from_layers(this->layers()), object_trafo * mv->get_matrix(), nullptr, &projected, vertical_points, [](){}); // Merge these projections with the output, layer by layer. assert(! projected.empty()); assert(out.empty() || out.size() == projected.size()); diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp index b65c79d0eb..c421dc52cc 100644 --- a/src/libslic3r/PrintObjectSlice.cpp +++ b/src/libslic3r/PrintObjectSlice.cpp @@ -1799,6 +1799,13 @@ ExPolygons PrintObject::_shrink_contour_holes(double contour_delta, double hole_ return union_ex(new_ex_polys); } +Transform3d PrintObject::trafo_sliced() const +{ + Transform3d trafo = this->trafo_centered(); + BeltSliceStrategy::apply_preslice_transforms(trafo, this->print()->config(), this->model_object()->volumes); + return trafo; +} + std::vector PrintObject::slice_support_volumes(const ModelVolumeType model_volume_type) const { auto it_volume = this->model_object()->volumes.begin(); @@ -1813,7 +1820,7 @@ std::vector PrintObject::slice_support_volumes(const ModelVolumeType m const Print *print = this->print(); auto throw_on_cancel_callback = std::function([print](){ print->throw_if_canceled(); }); MeshSlicingParamsEx params; - params.trafo = this->trafo_centered(); + params.trafo = this->trafo_sliced(); for (; it_volume != it_volume_end; ++ it_volume) if ((*it_volume)->type() == model_volume_type) { std::vector slices2 = slice_volume(*(*it_volume), zs, params, throw_on_cancel_callback);