mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-17 02:22:17 +00:00
Add fuzzy skin painting (#9979)
* SPE-2486: Refactor function apply_mm_segmentation() to prepare support for fuzzy skin painting. (cherry picked from commit 2c06c81159f7aadd6ac20c7a7583c8f4959a5601) * SPE-2585: Fix empty layers when multi-material painting and modifiers are used. (cherry picked from commit 4b3da02ec26d43bfad91897cb34779fb21419e3e) * Update project structure to match Prusa * SPE-2486: Add a new gizmo for fuzzy skin painting. (cherry picked from commit 886faac74ebe6978b828f51be62d26176e2900e5) * Fix render * Remove duplicated painting gizmo `render_triangles` code * SPE-2486: Extend multi-material segmentation to allow segmentation of any painted faces. (cherry picked from commit 519f5eea8e3be0d7c2cd5d030323ff264727e3d0) --------- Co-authored-by: Lukáš Hejl <hejl.lukas@gmail.com> * SPE-2486: Implement segmentation of layers based on fuzzy skin painting. (cherry picked from commit 800b742b950438c5ed8323693074b6171300131c) * SPE-2486: Separate fuzzy skin implementation into the separate file. (cherry picked from commit efd95c1c66dc09fca7695fb82405056c687c2291) * Move more fuzzy code to separate file * Don't hide fuzzy skin option, so it can be applied to paint on fuzzy * Fix build * Add option group for fuzzy skin * Update icon color * Fix reset painting * Update UI style * Store fuzzy painting in bbs_3mf * Add missing fuzzy paint code * SPE-2486: Limit the depth of the painted fuzzy skin regions to make regions cover just external perimeters. This reduces the possibility of artifacts that could happen during regions merging. (cherry picked from commit fa2663f02647f80b239da4f45d92ef66f5ce048a) * Update icons --------- Co-authored-by: yw4z <ywsyildiz@gmail.com> * Make the region compatible check a separate function * Only warn about multi-material if it's truly multi-perimeters * Improve gizmo UI & tooltips --------- Co-authored-by: Lukáš Hejl <hejl.lukas@gmail.com> Co-authored-by: yw4z <ywsyildiz@gmail.com>
This commit is contained in:
@@ -77,6 +77,8 @@ static inline void model_volume_list_copy_configs(ModelObject &model_object_dst,
|
||||
mv_dst.seam_facets.assign(mv_src.seam_facets);
|
||||
assert(mv_dst.mmu_segmentation_facets.id() == mv_src.mmu_segmentation_facets.id());
|
||||
mv_dst.mmu_segmentation_facets.assign(mv_src.mmu_segmentation_facets);
|
||||
assert(mv_dst.fuzzy_skin_facets.id() == mv_src.fuzzy_skin_facets.id());
|
||||
mv_dst.fuzzy_skin_facets.assign(mv_src.fuzzy_skin_facets);
|
||||
//FIXME what to do with the materials?
|
||||
// mv_dst.m_material_id = mv_src.m_material_id;
|
||||
++ i_src;
|
||||
@@ -705,7 +707,6 @@ bool verify_update_print_object_regions(
|
||||
ModelVolumePtrs model_volumes,
|
||||
const PrintRegionConfig &default_region_config,
|
||||
size_t num_extruders,
|
||||
const std::vector<unsigned int> &painting_extruders,
|
||||
PrintObjectRegions &print_object_regions,
|
||||
const std::function<void(const PrintRegionConfig&, const PrintRegionConfig&, const t_config_option_keys&)> &callback_invalidate)
|
||||
{
|
||||
@@ -803,6 +804,29 @@ bool verify_update_print_object_regions(
|
||||
print_region_ref_inc(*region.region);
|
||||
}
|
||||
|
||||
// Verify and / or update PrintRegions produced by fuzzy skin painting.
|
||||
for (const PrintObjectRegions::LayerRangeRegions &layer_range : print_object_regions.layer_ranges) {
|
||||
for (const PrintObjectRegions::FuzzySkinPaintedRegion ®ion : layer_range.fuzzy_skin_painted_regions) {
|
||||
const PrintRegion &parent_print_region = *region.parent_print_object_region(layer_range);
|
||||
PrintRegionConfig cfg = parent_print_region.config();
|
||||
cfg.fuzzy_skin.value = FuzzySkinType::All;
|
||||
if (cfg != region.region->config()) {
|
||||
// Region configuration changed.
|
||||
if (print_region_ref_cnt(*region.region) == 0) {
|
||||
// Region is referenced for the first time. Just change its parameters.
|
||||
// Stop the background process before assigning new configuration to the regions.
|
||||
t_config_option_keys diff = region.region->config().diff(cfg);
|
||||
callback_invalidate(region.region->config(), cfg, diff);
|
||||
region.region->config_apply_only(cfg, diff, false);
|
||||
} else {
|
||||
// Region is referenced multiple times, thus the region is being split. We need to reslice.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
print_region_ref_inc(*region.region);
|
||||
}
|
||||
}
|
||||
|
||||
// Lastly verify, whether some regions were not merged.
|
||||
{
|
||||
std::vector<const PrintRegion*> regions;
|
||||
@@ -906,7 +930,8 @@ static PrintObjectRegions* generate_print_object_regions(
|
||||
const Transform3d &trafo,
|
||||
size_t num_extruders,
|
||||
const float xy_contour_compensation,
|
||||
const std::vector<unsigned int> & painting_extruders)
|
||||
const std::vector<unsigned int> &painting_extruders,
|
||||
const bool has_painted_fuzzy_skin)
|
||||
{
|
||||
// Reuse the old object or generate a new one.
|
||||
auto out = print_object_regions_old ? std::unique_ptr<PrintObjectRegions>(print_object_regions_old) : std::make_unique<PrintObjectRegions>();
|
||||
@@ -928,6 +953,7 @@ static PrintObjectRegions* generate_print_object_regions(
|
||||
r.config = range.config;
|
||||
r.volume_regions.clear();
|
||||
r.painted_regions.clear();
|
||||
r.fuzzy_skin_painted_regions.clear();
|
||||
}
|
||||
} else {
|
||||
out->trafo_bboxes = trafo;
|
||||
@@ -1009,13 +1035,42 @@ static PrintObjectRegions* generate_print_object_regions(
|
||||
cfg.sparse_infill_filament.value = painted_extruder_id;
|
||||
layer_range.painted_regions.push_back({ painted_extruder_id, parent_region_id, get_create_region(std::move(cfg))});
|
||||
}
|
||||
// Sort the regions by parent region::print_object_region_id() and extruder_id to help the slicing algorithm when applying MMU segmentation.
|
||||
// Sort the regions by parent region::print_object_region_id() and extruder_id to help the slicing algorithm when applying MM segmentation.
|
||||
std::sort(layer_range.painted_regions.begin(), layer_range.painted_regions.end(), [&layer_range](auto &l, auto &r) {
|
||||
int lid = layer_range.volume_regions[l.parent].region->print_object_region_id();
|
||||
int rid = layer_range.volume_regions[r.parent].region->print_object_region_id();
|
||||
return lid < rid || (lid == rid && l.extruder_id < r.extruder_id); });
|
||||
}
|
||||
|
||||
if (has_painted_fuzzy_skin) {
|
||||
using FuzzySkinParentType = PrintObjectRegions::FuzzySkinPaintedRegion::ParentType;
|
||||
|
||||
for (PrintObjectRegions::LayerRangeRegions &layer_range : layer_ranges_regions) {
|
||||
// FuzzySkinPaintedRegion can override different parts of the Layer than PaintedRegions,
|
||||
// so FuzzySkinPaintedRegion has to point to both VolumeRegion and PaintedRegion.
|
||||
for (int parent_volume_region_id = 0; parent_volume_region_id < int(layer_range.volume_regions.size()); ++parent_volume_region_id) {
|
||||
if (const PrintObjectRegions::VolumeRegion &parent_volume_region = layer_range.volume_regions[parent_volume_region_id]; parent_volume_region.model_volume->is_model_part() || parent_volume_region.model_volume->is_modifier()) {
|
||||
PrintRegionConfig cfg = parent_volume_region.region->config();
|
||||
cfg.fuzzy_skin.value = FuzzySkinType::All;
|
||||
layer_range.fuzzy_skin_painted_regions.push_back({FuzzySkinParentType::VolumeRegion, parent_volume_region_id, get_create_region(std::move(cfg))});
|
||||
}
|
||||
}
|
||||
|
||||
for (int parent_painted_regions_id = 0; parent_painted_regions_id < int(layer_range.painted_regions.size()); ++parent_painted_regions_id) {
|
||||
const PrintObjectRegions::PaintedRegion &parent_painted_region = layer_range.painted_regions[parent_painted_regions_id];
|
||||
|
||||
PrintRegionConfig cfg = parent_painted_region.region->config();
|
||||
cfg.fuzzy_skin.value = FuzzySkinType::All;
|
||||
layer_range.fuzzy_skin_painted_regions.push_back({FuzzySkinParentType::PaintedRegion, parent_painted_regions_id, get_create_region(std::move(cfg))});
|
||||
}
|
||||
|
||||
// Sort the regions by parent region::print_object_region_id() to help the slicing algorithm when applying fuzzy skin segmentation.
|
||||
std::sort(layer_range.fuzzy_skin_painted_regions.begin(), layer_range.fuzzy_skin_painted_regions.end(), [&layer_range](auto &l, auto &r) {
|
||||
return l.parent_print_object_region_id(layer_range) < r.parent_print_object_region_id(layer_range);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return out.release();
|
||||
}
|
||||
|
||||
@@ -1251,7 +1306,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
// Only volume IDs, volume types, transformation matrices and their order are checked, configuration and other parameters are NOT checked.
|
||||
bool solid_or_modifier_differ = model_volume_list_changed(model_object, model_object_new, solid_or_modifier_types) ||
|
||||
model_mmu_segmentation_data_changed(model_object, model_object_new) ||
|
||||
(model_object_new.is_mm_painted() && num_extruders_changed );
|
||||
(model_object_new.is_mm_painted() && num_extruders_changed) ||
|
||||
model_fuzzy_skin_data_changed(model_object, model_object_new);
|
||||
bool supports_differ = model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_BLOCKER) ||
|
||||
model_volume_list_changed(model_object, model_object_new, ModelVolumeType::SUPPORT_ENFORCER);
|
||||
bool layer_height_ranges_differ = ! layer_height_ranges_equal(model_object.layer_config_ranges, model_object_new.layer_config_ranges, model_object_new.layer_height_profile.empty());
|
||||
@@ -1541,8 +1597,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
verify_update_print_object_regions(
|
||||
print_object.model_object()->volumes,
|
||||
m_default_region_config,
|
||||
num_extruders ,
|
||||
painting_extruders,
|
||||
num_extruders,
|
||||
*print_object_regions,
|
||||
[it_print_object, it_print_object_end, &update_apply_status](const PrintRegionConfig &old_config, const PrintRegionConfig &new_config, const t_config_option_keys &diff_keys) {
|
||||
for (auto it = it_print_object; it != it_print_object_end; ++it)
|
||||
@@ -1569,7 +1624,8 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||
model_object_status.print_instances.front().trafo,
|
||||
num_extruders ,
|
||||
print_object.is_mm_painted() ? 0.f : float(print_object.config().xy_contour_compensation.value),
|
||||
painting_extruders);
|
||||
painting_extruders,
|
||||
print_object.is_fuzzy_skin_painted());
|
||||
}
|
||||
for (auto it = it_print_object; it != it_print_object_end; ++it)
|
||||
if ((*it)->m_shared_regions) {
|
||||
|
||||
Reference in New Issue
Block a user