From 4b3da02ec26d43bfad91897cb34779fb21419e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 5 Dec 2024 14:46:48 +0100 Subject: [PATCH] SPE-2585: Fix empty layers when multi-material painting and modifiers are used. --- src/libslic3r/PrintObjectSlice.cpp | 37 ++++++++++++++++-------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/libslic3r/PrintObjectSlice.cpp b/src/libslic3r/PrintObjectSlice.cpp index 1e819876f3..2c043f840e 100644 --- a/src/libslic3r/PrintObjectSlice.cpp +++ b/src/libslic3r/PrintObjectSlice.cpp @@ -595,12 +595,13 @@ void apply_mm_segmentation(PrintObject &print_object, ThrowOnCancel throw_on_can BoundingBox bbox; }; - std::vector by_extruder; struct ByRegion { - ExPolygons expolygons; - bool needs_merge { false }; + ExPolygons expolygons; + bool needs_merge { false }; }; - std::vector by_region; + + std::vector by_extruder; + std::vector by_region; for (size_t layer_id = range.begin(); layer_id < range.end(); ++layer_id) { throw_on_cancel(); Layer &layer = *print_object.get_layer(int(layer_id)); @@ -645,34 +646,36 @@ void apply_mm_segmentation(PrintObject &print_object, ThrowOnCancel throw_on_can assert(&parent_print_region == layer_range.volume_regions[it_first_painted_region->parent].region); - // Find the first PaintedRegion with different parent PrintRegion. - auto it_last_painted_region = std::find_if(it_first_painted_region, layer_range.painted_regions.cend(), [&it_first_painted_region](const auto &painted_region) { - return painted_region.parent != it_first_painted_region->parent; - }); - // Update the beginning PaintedRegion iterator for the next iteration. - it_painted_region_begin = it_last_painted_region; + it_painted_region_begin = it_first_painted_region; const BoundingBox parent_layer_region_bbox = get_extents(parent_layer_region.slices().surfaces); bool self_trimmed = false; int self_extruder_id = -1; // 1-based extruder ID - for (auto it_painted_region = it_first_painted_region; it_painted_region != it_last_painted_region; ++it_painted_region) { - const int extruder_id = int(it_painted_region->extruder_id); // 1-based extruder ID - assert(extruder_id > 0 && (extruder_id - 1) < int(by_extruder.size())); - assert(layer_range.volume_regions[it_painted_region->parent].region == &parent_print_region); - + for (int extruder_id = 1; extruder_id <= int(by_extruder.size()); ++extruder_id) { const ByExtruder &segmented = by_extruder[extruder_id - 1]; if (!segmented.bbox.defined || !parent_layer_region_bbox.overlap(segmented.bbox)) continue; + // Find the first target region iterator. + auto it_target_region = std::find_if(it_painted_region_begin, layer_range.painted_regions.cend(), [extruder_id](const auto &painted_region) { + return int(painted_region.extruder_id) >= extruder_id; + }); + + assert(it_target_region != layer_range.painted_regions.end()); + assert(layer_range.volume_regions[it_target_region->parent].region == &parent_print_region && int(it_target_region->extruder_id) == extruder_id); + + // Update the beginning PaintedRegion iterator for the next iteration. + it_painted_region_begin = it_target_region; + // FIXME: Don't trim by self, it is not reliable. - if (it_painted_region->region == &parent_print_region) { + if (it_target_region->region == &parent_print_region) { self_extruder_id = extruder_id; continue; } // Steal from this region. - int target_region_id = it_painted_region->region->print_object_region_id(); + int target_region_id = it_target_region->region->print_object_region_id(); ExPolygons stolen = intersection_ex(parent_layer_region.slices().surfaces, segmented.expolygons); if (!stolen.empty()) { ByRegion &dst = by_region[target_region_id];