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().
This commit is contained in:
Hanif Koh
2026-09-14 01:32:07 +08:00
parent 5de5cdd8f8
commit d0c068a230
5 changed files with 21 additions and 7 deletions
+2 -2
View File
@@ -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()) {
+1 -1
View File
@@ -1215,7 +1215,7 @@ static inline std::vector<std::vector<ExPolygons>> segmentation_top_and_bottom_l
// project downards pointing painted triangles over bottom surfaces.
std::vector<std::vector<Polygons>> top_raw(num_facets_states), bottom_raw(num_facets_states);
std::vector<float> 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;
+3
View File
@@ -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<double>(m_center_offset.x()), - unscale<double>(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; }
+7 -3
View File
@@ -1072,7 +1072,10 @@ std::pair<FillAdaptive::OctreePtr, FillAdaptive::OctreePtr> 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<std::vector<Vec3d>> 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<Polygons>& out, std::vector<std::pair<Vec3f, Vec3f>>* 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<float>(),
(object_trafo * mv->get_matrix()).cast<float>(),
seam, out);
else {
std::vector<Polygons> 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());
+8 -1
View File
@@ -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<Polygons> PrintObject::slice_support_volumes(const ModelVolumeType model_volume_type) const
{
auto it_volume = this->model_object()->volumes.begin();
@@ -1813,7 +1820,7 @@ std::vector<Polygons> PrintObject::slice_support_volumes(const ModelVolumeType m
const Print *print = this->print();
auto throw_on_cancel_callback = std::function<void()>([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<ExPolygons> slices2 = slice_volume(*(*it_volume), zs, params, throw_on_cancel_callback);