SPE-1841: Replace default extruder with volume extruder for multi-material segmentation.

Previously, the default extruder wasn't handled inside multi-material segmentation, but this could confuse users, especially for multi-volume objects.
Because with multi-volume, it could happen that in the place where two volumes were touching, there could be a change in the used extruder.
This commit is contained in:
Lukáš Hejl 2024-10-29 10:06:32 +01:00 committed by Lukas Matena
parent 3edec09a2e
commit 84e9da9c6c
5 changed files with 45 additions and 15 deletions

View File

@ -2588,12 +2588,10 @@ namespace Slic3r {
assert(index < geometry.custom_supports.size());
assert(index < geometry.custom_seam.size());
assert(index < geometry.mm_segmentation.size());
if (! geometry.custom_supports[index].empty())
volume->supported_facets.set_triangle_from_string(i, geometry.custom_supports[index]);
if (! geometry.custom_seam[index].empty())
volume->seam_facets.set_triangle_from_string(i, geometry.custom_seam[index]);
if (! geometry.mm_segmentation[index].empty())
volume->mm_segmentation_facets.set_triangle_from_string(i, geometry.mm_segmentation[index]);
volume->supported_facets.set_triangle_from_string(i, geometry.custom_supports[index]);
volume->seam_facets.set_triangle_from_string(i, geometry.custom_seam[index]);
volume->mm_segmentation_facets.set_triangle_from_string(i, geometry.mm_segmentation[index]);
}
volume->supported_facets.shrink_to_fit();
volume->seam_facets.shrink_to_fit();

View File

@ -2122,9 +2122,15 @@ std::string FacetsAnnotation::get_triangle_as_string(int triangle_idx) const
// Recover triangle splitting & state from string of hexadecimal values previously
// generated by get_triangle_as_string. Used to load from 3MF.
void FacetsAnnotation::set_triangle_from_string(int triangle_id, const std::string& str)
void FacetsAnnotation::set_triangle_from_string(int triangle_id, const std::string &str)
{
assert(! str.empty());
if (str.empty()) {
// The triangle isn't painted, so it means that it will use the default extruder.
m_data.used_states[static_cast<int>(TriangleStateType::NONE)] = true;
return;
}
assert(!str.empty());
assert(m_data.triangles_to_split.empty() || m_data.triangles_to_split.back().triangle_idx < triangle_id);
m_data.triangles_to_split.emplace_back(triangle_id, int(m_data.bitstream.size()));

View File

@ -1611,6 +1611,26 @@ static indexed_triangle_set_with_color extract_mesh_with_color(const ModelVolume
return volume.mm_segmentation_facets.get_all_facets_strict_with_colors(volume);
}
static std::vector<ColorPolygons> slice_model_volume_with_color(const ModelVolume &model_volume, const std::vector<float> &layer_zs, const PrintObject &print_object)
{
const indexed_triangle_set_with_color mesh_with_color = extract_mesh_with_color(model_volume);
const Transform3d trafo = print_object.trafo_centered() * model_volume.get_matrix();
const MeshSlicingParams slicing_params{trafo};
std::vector<ColorPolygons> color_polygons_per_layer = slice_mesh(mesh_with_color, layer_zs, slicing_params);
// Replace default painted color (TriangleStateType::NONE) with volume extruder.
if (const int volume_extruder_id = model_volume.extruder_id(); volume_extruder_id > 0 && model_volume.is_mm_painted()) {
for (ColorPolygons &color_polygons : color_polygons_per_layer) {
for (ColorPolygon &color_polygon : color_polygons) {
std::replace(color_polygon.colors.begin(), color_polygon.colors.end(), static_cast<uint8_t>(TriangleStateType::NONE), static_cast<uint8_t>(volume_extruder_id));
}
}
}
return color_polygons_per_layer;
}
std::vector<std::vector<ExPolygons>> multi_material_segmentation_by_painting(const PrintObject &print_object, const std::function<void()> &throw_on_cancel_callback)
{
const size_t num_extruders = print_object.print()->config().nozzle_diameter.size();
@ -1659,11 +1679,7 @@ std::vector<std::vector<ExPolygons>> multi_material_segmentation_by_painting(con
BOOST_LOG_TRIVIAL(debug) << "MM segmentation - Slicing painted triangles - Begin";
const std::vector<float> layer_zs = get_print_object_layers_zs(layers);
for (const ModelVolume *mv : print_object.model_object()->volumes) {
const indexed_triangle_set_with_color mesh_with_color = extract_mesh_with_color(*mv);
const Transform3d trafo = print_object.trafo_centered() * mv->get_matrix();
const MeshSlicingParams slicing_params{trafo};
std::vector<ColorPolygons> color_polygons_per_layer = slice_mesh(mesh_with_color, layer_zs, slicing_params);
std::vector<ColorPolygons> color_polygons_per_layer = slice_model_volume_with_color(*mv, layer_zs, print_object);
tbb::parallel_for(tbb::blocked_range<size_t>(0, num_layers), [&color_polygons_per_layer, &color_polygons_lines_layers, &throw_on_cancel_callback](const tbb::blocked_range<size_t> &range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++layer_idx) {

View File

@ -1410,17 +1410,24 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
const std::vector<bool> &volume_used_facet_states = volume->mm_segmentation_facets.get_data().used_states;
assert(volume_used_facet_states.size() == used_facet_states.size());
for (size_t state_idx = 0; state_idx < std::min(volume_used_facet_states.size(), used_facet_states.size()); ++state_idx) {
for (size_t state_idx = 1; state_idx < std::min(volume_used_facet_states.size(), used_facet_states.size()); ++state_idx) {
used_facet_states[state_idx] |= volume_used_facet_states[state_idx];
}
// When the default facet state (TriangleStateType::NONE) is used, then we mark the volume extruder also as the used extruder.
const bool used_volume_extruder = !volume_used_facet_states.empty() && volume_used_facet_states[static_cast<size_t>(TriangleStateType::NONE)];
if (const int volume_extruder_id = volume->extruder_id(); used_volume_extruder && volume_extruder_id >= 0) {
used_facet_states[volume_extruder_id] |= true;
}
} else if (const int volume_extruder_id = volume->extruder_id(); volume_extruder_id >= 0) {
used_facet_states[volume_extruder_id] |= true;
}
}
for (size_t state_idx = static_cast<size_t>(TriangleStateType::Extruder1); state_idx < used_facet_states.size(); ++state_idx) {
if (used_facet_states[state_idx])
if (used_facet_states[state_idx]) {
painting_extruders.emplace_back(state_idx);
}
}
}
if (model_object_status.print_object_regions_status == ModelObjectStatus::PrintObjectRegionsStatus::Valid) {

View File

@ -1658,6 +1658,9 @@ TriangleSelector::TriangleSplittingData TriangleSelector::serialize() const {
out.data.triangles_to_split.emplace_back(i, int(out.data.bitstream.size()));
// out the triangle bits.
out.serialize(i);
} else if (!tr.is_split()) {
assert(tr.get_state() == TriangleStateType::NONE);
out.data.used_states[static_cast<int>(TriangleStateType::NONE)] = true;
}
// May be stored onto Undo / Redo stack, thus conserve memory.