diff --git a/src/libslic3r/MultiMaterialSegmentation.cpp b/src/libslic3r/MultiMaterialSegmentation.cpp index c3f2fed13d..aa25361083 100644 --- a/src/libslic3r/MultiMaterialSegmentation.cpp +++ b/src/libslic3r/MultiMaterialSegmentation.cpp @@ -1121,13 +1121,13 @@ static void cut_segmented_layers(const ConstLayerPtrsAdaptor layers, std::vector // Returns MMU segmentation of top and bottom layers based on painting in MMU segmentation gizmo static inline std::vector> mmu_segmentation_top_and_bottom_layers(const PrintObject &print_object) { + const size_t num_extruders = print_object.print()->config().nozzle_diameter.size(); const ConstLayerPtrsAdaptor layers = print_object.layers(); - std::vector> triangles_by_color(3); - triangles_by_color.assign(3, std::vector(layers.size())); + std::vector> triangles_by_color(num_extruders); + triangles_by_color.assign(num_extruders, std::vector(layers.size())); for (const ModelVolume *mv : print_object.model_object()->volumes) { - for (const auto ¶ms : {std::make_pair(EnforcerBlockerType::NONE, 0), std::make_pair(EnforcerBlockerType::ENFORCER, 1), - std::make_pair(EnforcerBlockerType::BLOCKER, 2)}) { - const indexed_triangle_set custom_facets = mv->mmu_segmentation_facets.get_facets(*mv, params.first); + for (size_t extruder_idx = 0; extruder_idx < num_extruders; ++extruder_idx) { + const indexed_triangle_set custom_facets = mv->mmu_segmentation_facets.get_facets(*mv, EnforcerBlockerType(extruder_idx)); if (!mv->is_model_part() || custom_facets.indices.empty()) continue; @@ -1168,7 +1168,7 @@ static inline std::vector> mmu_segmentation_top_and_bott for (auto layer_it = first_layer; (layer_it != (last_layer + 1) && layer_it != layers.end()); ++layer_it) { size_t layer_idx = layer_it - layers.begin(); - triangles_by_color[params.second][layer_idx].emplace_back(triangle); + triangles_by_color[extruder_idx][layer_idx].emplace_back(triangle); } } } @@ -1234,10 +1234,10 @@ static inline std::vector> mmu_segmentation_top_and_bott } }); // end of parallel_for - std::vector> triangles_by_color_bottom(3); - std::vector> triangles_by_color_top(3); - triangles_by_color_bottom.assign(3, std::vector(layers.size())); - triangles_by_color_top.assign(3, std::vector(layers.size())); + std::vector> triangles_by_color_bottom(num_extruders); + std::vector> triangles_by_color_top(num_extruders); + triangles_by_color_bottom.assign(num_extruders, std::vector(layers.size())); + triangles_by_color_top.assign(num_extruders, std::vector(layers.size())); for (size_t layer_idx = 0; layer_idx < print_object.layers().size(); ++layer_idx) { BOOST_LOG_TRIVIAL(debug) << "MMU segmentation of top layer: " << layer_idx; @@ -1306,8 +1306,8 @@ static inline std::vector> mmu_segmentation_top_and_bott } } - std::vector> triangles_by_color_merged(3); - triangles_by_color_merged.assign(3, std::vector(layers.size())); + std::vector> triangles_by_color_merged(num_extruders); + triangles_by_color_merged.assign(num_extruders, std::vector(layers.size())); for (size_t layer_idx = 0; layer_idx < layers.size(); ++layer_idx) { for (size_t color_idx = 0; color_idx < triangles_by_color_merged.size(); ++color_idx) { auto &self = triangles_by_color_merged[color_idx][layer_idx]; @@ -1367,8 +1367,9 @@ std::vector>> multi_material_segmentati } for (const ModelVolume *mv : print_object.model_object()->volumes) { - for (const auto ¶ms : {std::make_pair(EnforcerBlockerType::ENFORCER, 1), std::make_pair(EnforcerBlockerType::BLOCKER, 2)}) { - const indexed_triangle_set custom_facets = mv->mmu_segmentation_facets.get_facets(*mv, params.first); + const size_t num_extruders = print_object.print()->config().nozzle_diameter.size(); + for (size_t extruder_idx = 1; extruder_idx < num_extruders; ++extruder_idx) { + const indexed_triangle_set custom_facets = mv->mmu_segmentation_facets.get_facets(*mv, EnforcerBlockerType(extruder_idx)); if (!mv->is_model_part() || custom_facets.indices.empty()) continue; @@ -1425,7 +1426,7 @@ std::vector>> multi_material_segmentati visitor.reset(); visitor.line_to_test.a = line_start; visitor.line_to_test.b = line_end; - visitor.color = params.second; + visitor.color = extruder_idx; edge_grids[layer_idx].visit_cells_intersecting_line(line_start, line_end, visitor); append(painted_lines[layer_idx], std::move(painted_line_tmp)); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index a1d8f65bfe..1c5c4f0216 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1918,7 +1918,8 @@ void PrintObject::_slice(const std::vector &layer_height_profile) size_t region_count_before_change = this->num_regions(); std::vector>> segmented_regions = multi_material_segmentation_by_painting(*this); // Skip region with default extruder - for (size_t region_idx = 1; region_idx < 3; ++region_idx) { + const size_t num_extruders = this->print()->config().nozzle_diameter.size(); + for (size_t region_idx = 1; region_idx < num_extruders; ++region_idx) { std::vector c_layers(m_layers.size()); for (size_t layer_idx = 0; layer_idx < m_layers.size(); ++layer_idx) { for(const std::pair &colored_polygon : segmented_regions[layer_idx]) { diff --git a/src/libslic3r/TriangleSelector.cpp b/src/libslic3r/TriangleSelector.cpp index 7570075e56..ad69f6c7f9 100644 --- a/src/libslic3r/TriangleSelector.cpp +++ b/src/libslic3r/TriangleSelector.cpp @@ -550,8 +550,9 @@ indexed_triangle_set TriangleSelector::get_facets(EnforcerBlockerType state) con std::map> TriangleSelector::serialize() const { // Each original triangle of the mesh is assigned a number encoding its state - // or how it is split. Each triangle is encoded by 4 bits (xxyy): - // leaf triangle: xx = EnforcerBlockerType, yy = 0 + // or how it is split. Each triangle is encoded by 4 bits (xxyy) or 8 bits (zzzzxxyy): + // leaf triangle: xx = EnforcerBlockerType (Only values 0, 1, and 2. Value 3 is used as an indicator for additional 4 bits.), yy = 0 + // leaf triangle: xx = 0b11, yy = 0b00, zzzz = EnforcerBlockerType (subtracted by 3) // non-leaf: xx = special side, yy = number of split sides // These are bitwise appended and formed into one 64-bit integer. @@ -594,9 +595,17 @@ std::map> TriangleSelector::serialize() const serialize_recursive(tr.children[child_idx]); } else { // In case this is leaf, we better save information about its state. - assert(int(tr.get_state()) <= 3); - data.push_back(int(tr.get_state()) & 0b01); - data.push_back(int(tr.get_state()) & 0b10); + assert(int(tr.get_state()) <= 15); + if (3 <= int(tr.get_state()) && int(tr.get_state()) <= 15) { + data.insert(data.end(), {true, true}); + for (size_t bit_idx = 0; bit_idx < 4; ++bit_idx) { + size_t bit_mask = 0b0001 << bit_idx; + data.push_back(int(tr.get_state()) - 3 & bit_mask); + } + } else { + data.push_back(int(tr.get_state()) & 0b01); + data.push_back(int(tr.get_state()) & 0b10); + } ++stored_triangles; } }; @@ -614,7 +623,7 @@ void TriangleSelector::deserialize(const std::map> data) for (const auto& [triangle_id, code] : data) { assert(triangle_id < int(m_triangles.size())); assert(! code.empty()); - int processed_triangles = 0; + int processed_nibbles = 0; struct ProcessingInfo { int facet_id = 0; int processed_children = 0; @@ -626,18 +635,26 @@ void TriangleSelector::deserialize(const std::map> data) while (true) { // Read next triangle info. - int next_code = 0; - for (int i=3; i>=0; --i) { - next_code = next_code << 1; - next_code |= int(code[4 * processed_triangles + i]); - } - ++processed_triangles; + std::array next_code{}; + for(size_t nibble_idx = 0; nibble_idx < 2; ++nibble_idx) { + assert(nibble_idx < 2); + if(nibble_idx >= 1 && (next_code[0] >> 2) != 0b11) + break; - int num_of_split_sides = (next_code & 0b11); + for (int i = 3; i >= 0; --i) { + next_code[nibble_idx] = next_code[nibble_idx] << 1; + next_code[nibble_idx] |= int(code[4 * processed_nibbles + i]); + } + + ++processed_nibbles; + } + + int num_of_split_sides = (next_code[0] & 0b11); int num_of_children = num_of_split_sides != 0 ? num_of_split_sides + 1 : 0; bool is_split = num_of_children != 0; - EnforcerBlockerType state = EnforcerBlockerType(next_code >> 2); - int special_side = (next_code >> 2); + // Value of the second nibble was subtracted by 3, so it is added back. + EnforcerBlockerType state = EnforcerBlockerType(next_code[0] >> 2 == 0b11 ? next_code[1] + 3 : next_code[0] >> 2); + int special_side = (next_code[0] >> 2); // Take care of the first iteration separately, so handling of the others is simpler. if (parents.empty()) {