diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 85fbe2919c5..035092dbfb3 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -504,6 +505,7 @@ struct TopSurfaceImageRegionPlan { bool contoning_polygonize_color_regions_enabled = false; int contoning_polygonize_resolution = TextureMappingZone::DefaultTopSurfaceContoningPolygonizeResolution; bool contoning_surface_anchored_stacks_enabled = false; + bool contoning_surface_anchored_stack_optimizations_enabled = TextureMappingZone::DefaultTopSurfaceContoningSurfaceAnchoredStackOptimizationsEnabled; bool contoning_td_adjustment_enabled = TextureMappingZone::DefaultTopSurfaceContoningTdAdjustmentEnabled; bool contoning_surface_scatter_enabled = TextureMappingZone::DefaultTopSurfaceContoningSurfaceScatterEnabled; bool contoning_beer_lambert_rgb_correction_enabled = TextureMappingZone::DefaultTopSurfaceContoningBeerLambertRgbCorrectionEnabled; @@ -1102,11 +1104,45 @@ static int top_surface_image_contoning_local_stack_layers_at_point(const Point & return layers; } -static ExPolygons top_surface_image_contoning_clean_area(ExPolygons &&component_area, - const ExPolygons &clip_area, - const ExPolygons &blocked_area, - float min_feature_mm, - const ThrowIfCanceled *throw_if_canceled) +static void top_surface_image_contoning_remove_collinear_points(Polygon &polygon) +{ + if (polygon.points.size() < 3) + return; + + Points points; + points.reserve(polygon.points.size()); + for (const Point &point : polygon.points) + if (points.empty() || points.back() != point) + points.emplace_back(point); + if (points.size() >= 2 && points.front() == points.back()) + points.pop_back(); + + bool changed = true; + while (changed && points.size() >= 3) { + changed = false; + Points filtered; + filtered.reserve(points.size()); + for (size_t idx = 0; idx < points.size(); ++idx) { + const Point &prev = points[(idx + points.size() - 1) % points.size()]; + const Point &point = points[idx]; + const Point &next = points[(idx + 1) % points.size()]; + if (point == prev || point == next || int128::orient(prev, point, next) == 0) { + changed = true; + continue; + } + filtered.emplace_back(point); + } + points = std::move(filtered); + } + + polygon.points = std::move(points); +} + +static ExPolygons top_surface_image_contoning_clean_area_impl(ExPolygons &&component_area, + const ExPolygons &clip_area, + const ExPolygons &blocked_area, + float min_feature_mm, + const ThrowIfCanceled *throw_if_canceled) { if (component_area.empty()) return {}; @@ -1142,10 +1178,166 @@ static ExPolygons top_surface_image_contoning_clean_area(ExPolygons &&component_ return filtered.empty() ? ExPolygons() : top_surface_clip_union_ex(filtered); } +struct TopSurfaceImageContoningCleanupGroup { + BoundingBox bbox; + ExPolygons area; +}; + +struct TopSurfaceImageContoningCleanupItem { + BoundingBox bbox; + ExPolygon area; +}; + +static void top_surface_image_contoning_merge_cleanup_group(std::vector &groups, + size_t group_idx, + const ThrowIfCanceled *throw_if_canceled) +{ + bool merged = true; + while (merged && group_idx < groups.size()) { + merged = false; + for (size_t idx = 0; idx < groups.size(); ++idx) { + if (idx == group_idx) + continue; + if (!groups[group_idx].bbox.defined || !groups[idx].bbox.defined || + !groups[group_idx].bbox.overlap(groups[idx].bbox)) + continue; + check_canceled(throw_if_canceled); + groups[group_idx].bbox.merge(groups[idx].bbox); + append(groups[group_idx].area, std::move(groups[idx].area)); + groups.erase(groups.begin() + idx); + if (idx < group_idx) + --group_idx; + merged = true; + break; + } + } +} + +static std::vector top_surface_image_contoning_cleanup_groups(ExPolygons &&component_area, + coord_t grouping_margin, + const ThrowIfCanceled *throw_if_canceled) +{ + std::vector items; + items.reserve(component_area.size()); + for (ExPolygon &expolygon : component_area) { + check_canceled(throw_if_canceled); + BoundingBox bbox = get_extents(expolygon); + if (bbox.defined && grouping_margin > 0) + bbox.offset(double(grouping_margin)); + items.push_back({ bbox, std::move(expolygon) }); + } + std::sort(items.begin(), items.end(), [](const TopSurfaceImageContoningCleanupItem &lhs, + const TopSurfaceImageContoningCleanupItem &rhs) { + if (lhs.bbox.defined != rhs.bbox.defined) + return lhs.bbox.defined; + if (!lhs.bbox.defined) + return false; + return std::make_tuple(lhs.bbox.min.x(), lhs.bbox.min.y(), lhs.bbox.max.x(), lhs.bbox.max.y()) < + std::make_tuple(rhs.bbox.min.x(), rhs.bbox.min.y(), rhs.bbox.max.x(), rhs.bbox.max.y()); + }); + + std::vector active; + std::vector groups; + active.reserve(items.size()); + groups.reserve(items.size()); + for (TopSurfaceImageContoningCleanupItem &item : items) { + check_canceled(throw_if_canceled); + if (!item.bbox.defined) { + TopSurfaceImageContoningCleanupGroup group; + group.bbox = item.bbox; + group.area.emplace_back(std::move(item.area)); + groups.emplace_back(std::move(group)); + continue; + } + + for (size_t idx = 0; idx < active.size();) { + if (active[idx].bbox.defined && active[idx].bbox.max.x() < item.bbox.min.x()) { + groups.emplace_back(std::move(active[idx])); + active.erase(active.begin() + idx); + } else { + ++idx; + } + } + + size_t group_idx = active.size(); + for (size_t idx = 0; idx < active.size(); ++idx) { + if (active[idx].bbox.defined && active[idx].bbox.overlap(item.bbox)) { + group_idx = idx; + break; + } + } + + if (group_idx == active.size()) { + TopSurfaceImageContoningCleanupGroup group; + group.bbox = item.bbox; + group.area.emplace_back(std::move(item.area)); + active.emplace_back(std::move(group)); + group_idx = active.size() - 1; + } else { + active[group_idx].bbox.merge(item.bbox); + active[group_idx].area.emplace_back(std::move(item.area)); + } + top_surface_image_contoning_merge_cleanup_group(active, group_idx, throw_if_canceled); + } + for (TopSurfaceImageContoningCleanupGroup &group : active) + groups.emplace_back(std::move(group)); + + std::vector out; + out.reserve(groups.size()); + for (TopSurfaceImageContoningCleanupGroup &group : groups) + if (!group.area.empty()) + out.emplace_back(std::move(group.area)); + return out; +} + +static ExPolygons top_surface_image_contoning_clean_area(ExPolygons &&component_area, + const ExPolygons &clip_area, + const ExPolygons &blocked_area, + float min_feature_mm, + bool cleanup_optimizations_enabled, + const ThrowIfCanceled *throw_if_canceled) +{ + if (!cleanup_optimizations_enabled || component_area.size() <= 1) + return top_surface_image_contoning_clean_area_impl(std::move(component_area), + clip_area, + blocked_area, + min_feature_mm, + throw_if_canceled); + + const float closing_radius = float(scale_(std::clamp(min_feature_mm * 0.18f, 0.05f, 0.45f))); + const double tolerance = scale_(std::clamp(min_feature_mm * 0.12f, 0.03f, 0.25f)); + const coord_t grouping_margin = + std::max(0, coord_t(std::ceil(double(closing_radius) + tolerance + double(SCALED_EPSILON)))); + std::vector groups = + top_surface_image_contoning_cleanup_groups(std::move(component_area), grouping_margin, throw_if_canceled); + if (groups.empty()) + return {}; + if (groups.size() == 1) + return top_surface_image_contoning_clean_area_impl(std::move(groups.front()), + clip_area, + blocked_area, + min_feature_mm, + throw_if_canceled); + + ExPolygons out; + for (ExPolygons &group : groups) { + check_canceled(throw_if_canceled); + ExPolygons cleaned = top_surface_image_contoning_clean_area_impl(std::move(group), + clip_area, + blocked_area, + min_feature_mm, + throw_if_canceled); + append(out, std::move(cleaned)); + } + return out; +} + struct TopSurfaceImageContoningVectorLabel { std::vector bottom_to_top; std::array rgb { { 0.f, 0.f, 0.f } }; std::array oklab { { 0.f, 0.f, 0.f } }; + int valid_depth { 0 }; + bool repeat_allowed { false }; }; struct TopSurfaceImageContoningVectorRegion { @@ -1249,6 +1441,7 @@ struct TopSurfaceImageContoningStackPlanKey { bool blue_noise { false }; bool polygonize { false }; int polygonize_resolution { 1 }; + bool surface_anchored_stack_optimizations { false }; bool td_adjustment { false }; bool surface_scatter { false }; bool beer_lambert_rgb_correction { false }; @@ -1282,6 +1475,7 @@ struct TopSurfaceImageContoningStackPlanKey { blue_noise, polygonize, polygonize_resolution, + surface_anchored_stack_optimizations, td_adjustment, surface_scatter, beer_lambert_rgb_correction, @@ -1312,6 +1506,7 @@ struct TopSurfaceImageContoningStackPlanKey { rhs.blue_noise, rhs.polygonize, rhs.polygonize_resolution, + rhs.surface_anchored_stack_optimizations, rhs.td_adjustment, rhs.surface_scatter, rhs.beer_lambert_rgb_correction, @@ -1689,6 +1884,7 @@ static ExPolygons top_surface_image_contoning_area_from_grid_label(const std::ve const ExPolygons &clip_area, const ExPolygons &blocked_area, float min_feature_mm, + bool cleanup_optimizations_enabled, const ThrowIfCanceled *throw_if_canceled) { ExPolygons cells; @@ -1730,7 +1926,12 @@ static ExPolygons top_surface_image_contoning_area_from_grid_label(const std::ve } for (const TopSurfaceImageContoningGridRect &rect : active) top_surface_image_contoning_append_grid_rect(cells, rect, min_x, min_y, step, bbox); - return top_surface_image_contoning_clean_area(std::move(cells), clip_area, blocked_area, min_feature_mm, throw_if_canceled); + return top_surface_image_contoning_clean_area(std::move(cells), + clip_area, + blocked_area, + min_feature_mm, + cleanup_optimizations_enabled, + throw_if_canceled); } static ExPolygons top_surface_image_contoning_polygonized_area_from_grid_label(const std::vector &grid, @@ -1744,6 +1945,7 @@ static ExPolygons top_surface_image_contoning_polygonized_area_from_grid_label(c const ExPolygons &clip_area, const ExPolygons &blocked_area, float min_feature_mm, + bool cleanup_optimizations_enabled, const ThrowIfCanceled *throw_if_canceled) { if (grid.empty() || cols <= 0 || rows <= 0 || grid.size() != size_t(cols) * size_t(rows)) @@ -1771,11 +1973,18 @@ static ExPolygons top_surface_image_contoning_polygonized_area_from_grid_label(c } if (polygon.points.size() >= 3 && polygon.points.front() == polygon.points.back()) polygon.points.pop_back(); + if (cleanup_optimizations_enabled) + top_surface_image_contoning_remove_collinear_points(polygon); if (polygon.points.size() >= 3) cells.emplace_back(std::move(polygon)); } - return top_surface_image_contoning_clean_area(std::move(cells), clip_area, blocked_area, min_feature_mm, throw_if_canceled); + return top_surface_image_contoning_clean_area(std::move(cells), + clip_area, + blocked_area, + min_feature_mm, + cleanup_optimizations_enabled, + throw_if_canceled); } static std::vector top_surface_image_contoning_component_regions_from_grid( @@ -1791,6 +2000,7 @@ static std::vector top_surface_image_conto const ExPolygons &area, float min_feature_mm, bool polygonize_color_regions, + bool cleanup_optimizations_enabled, bool lower_surface, const ThrowIfCanceled *throw_if_canceled) { @@ -1807,15 +2017,22 @@ static std::vector top_surface_image_conto return regions; std::vector component_grid(label_grid.size(), -1); + std::vector valid_grid(label_grid.size(), -1); std::vector cell_counts(size_t(max_component_id) + 1, 0); for (size_t idx = 0; idx < label_grid.size(); ++idx) { const int label = label_grid[idx]; if (label < 0 || label >= int(labels.size())) continue; - const std::vector &bottom_to_top = labels[size_t(label)].bottom_to_top; + const TopSurfaceImageContoningVectorLabel &label_data = labels[size_t(label)]; + const std::vector &bottom_to_top = label_data.bottom_to_top; if (bottom_to_top.empty()) continue; - const int pattern_depth = depth % int(bottom_to_top.size()); + const int valid_depth = label_data.valid_depth > 0 ? label_data.valid_depth : int(bottom_to_top.size()); + if (depth >= valid_depth) + continue; + const int pattern_depth = label_data.repeat_allowed ? depth % int(bottom_to_top.size()) : depth; + if (pattern_depth < 0 || pattern_depth >= int(bottom_to_top.size())) + continue; const unsigned int component_id = lower_surface ? bottom_to_top[size_t(pattern_depth)] : @@ -1823,6 +2040,7 @@ static std::vector top_surface_image_conto if (component_id == 0 || component_id > max_component_id) continue; component_grid[idx] = int(component_id); + valid_grid[idx] = 1; ++cell_counts[size_t(component_id)]; } @@ -1838,6 +2056,23 @@ static std::vector top_surface_image_conto return lhs < rhs; }); + const ExPolygons empty_blocked_area; + ExPolygons valid_area = top_surface_image_contoning_area_from_grid_label(valid_grid, + cols, + rows, + 1, + min_x, + min_y, + step, + bbox, + area, + empty_blocked_area, + min_feature_mm, + cleanup_optimizations_enabled, + throw_if_canceled); + if (valid_area.empty()) + return regions; + ExPolygons taken; for (int component_id : component_order) { check_canceled(throw_if_canceled); @@ -1851,9 +2086,10 @@ static std::vector top_surface_image_conto min_y, step, bbox, - area, + valid_area, taken, min_feature_mm, + cleanup_optimizations_enabled, throw_if_canceled) : top_surface_image_contoning_area_from_grid_label(component_grid, cols, @@ -1863,9 +2099,10 @@ static std::vector top_surface_image_conto min_y, step, bbox, - area, + valid_area, taken, min_feature_mm, + cleanup_optimizations_enabled, throw_if_canceled); if (component_area.empty()) continue; @@ -1880,7 +2117,7 @@ static std::vector top_surface_image_conto if (!regions.empty()) { check_canceled(throw_if_canceled); ExPolygons covered = top_surface_clip_union_ex(taken); - ExPolygons leftover = top_surface_clip_diff_ex(area, covered, ApplySafetyOffset::Yes); + ExPolygons leftover = top_surface_clip_diff_ex(valid_area, covered, ApplySafetyOffset::Yes); if (!leftover.empty()) { append(regions.front().area, std::move(leftover)); regions.front().area = top_surface_clip_union_ex(regions.front().area); @@ -1902,6 +2139,7 @@ static std::vector top_surface_image_conto const ExPolygons &area, float min_feature_mm, bool polygonize_color_regions, + bool cleanup_optimizations_enabled, const ThrowIfCanceled *throw_if_canceled) { std::vector regions; @@ -1943,6 +2181,7 @@ static std::vector top_surface_image_conto area, empty_blocked_area, min_feature_mm, + cleanup_optimizations_enabled, throw_if_canceled) : top_surface_image_contoning_area_from_grid_label(label_grid, cols, @@ -1955,6 +2194,7 @@ static std::vector top_surface_image_conto area, empty_blocked_area, min_feature_mm, + cleanup_optimizations_enabled, throw_if_canceled); if (label_area.empty()) continue; @@ -2351,6 +2591,8 @@ static std::optional top_surface_image_cont label_data.bottom_to_top = stack.bottom_to_top; label_data.rgb = *stack_rgb; label_data.oklab = color_solver_oklab_from_srgb(*stack_rgb); + label_data.valid_depth = std::max(visible_layers, int(stack.bottom_to_top.size())); + label_data.repeat_allowed = visible_layers > int(stack.bottom_to_top.size()); label = int(labels.size()); labels.emplace_back(std::move(label_data)); label_by_stack.emplace(label_key, label); @@ -2699,37 +2941,74 @@ static void top_surface_image_contoning_solve_anchored_region( anchored_region.union_area, plan.contoning_min_feature_mm, plan.contoning_polygonize_color_regions_enabled, + plan.contoning_surface_anchored_stack_optimizations_enabled, throw_if_canceled); anchored_region.depth_regions.resize(size_t(source_context.stack_layers)); + std::vector active_depths; + active_depths.reserve(size_t(source_context.stack_layers)); for (int depth = 0; depth < source_context.stack_layers; ++depth) { check_canceled(throw_if_canceled); - top_surface_image_contoning_report_anchored_progress(object, - source_layer, - source_surface, - L("processing"), - depth + 1, - source_context.stack_layers); - if (depth >= int(anchored_region.depth_areas.size()) || - anchored_region.depth_areas[size_t(depth)].empty()) - continue; - anchored_region.depth_regions[size_t(depth)] = - top_surface_image_contoning_component_regions_from_grid(grid, - cols, - rows, - labels, - depth, - min_x, - min_y, - step, - bbox, - anchored_region.union_area, - plan.contoning_min_feature_mm, - plan.contoning_polygonize_color_regions_enabled, - source_surface == TopSurfaceImageSourceSurface::Bottom && - plan.contoning_td_adjustment_enabled, - throw_if_canceled); + if (depth < int(anchored_region.depth_areas.size()) && + !anchored_region.depth_areas[size_t(depth)].empty()) + active_depths.emplace_back(depth); } + if (active_depths.empty()) + return; + + auto build_depth_regions = [&](int depth) { + check_canceled(throw_if_canceled); + return top_surface_image_contoning_component_regions_from_grid(grid, + cols, + rows, + labels, + depth, + min_x, + min_y, + step, + bbox, + anchored_region.union_area, + plan.contoning_min_feature_mm, + plan.contoning_polygonize_color_regions_enabled, + plan.contoning_surface_anchored_stack_optimizations_enabled, + source_surface == TopSurfaceImageSourceSurface::Bottom && + plan.contoning_td_adjustment_enabled, + throw_if_canceled); + }; + + top_surface_image_contoning_report_anchored_progress(object, + source_layer, + source_surface, + L("processing"), + 0, + int(active_depths.size())); + if (active_depths.size() <= 1) { + const int depth = active_depths.front(); + anchored_region.depth_regions[size_t(depth)] = build_depth_regions(depth); + } else { + std::atomic completed_depths { 0 }; + tbb::parallel_for(tbb::blocked_range(0, active_depths.size(), 1), + [&](const tbb::blocked_range &range) { + for (size_t idx = range.begin(); idx != range.end(); ++idx) { + const int depth = active_depths[idx]; + anchored_region.depth_regions[size_t(depth)] = build_depth_regions(depth); + const int completed = ++completed_depths; + if (completed == int(active_depths.size()) || (completed & 3) == 0) + top_surface_image_contoning_report_anchored_progress(object, + source_layer, + source_surface, + L("processing"), + completed, + int(active_depths.size())); + } + }); + } + top_surface_image_contoning_report_anchored_progress(object, + source_layer, + source_surface, + L("processing"), + int(active_depths.size()), + int(active_depths.size())); } static std::shared_ptr top_surface_image_contoning_build_anchored_surface_plan( @@ -2907,6 +3186,7 @@ static TopSurfaceImageContoningStackPlanKey top_surface_image_contoning_anchored key.polygonize_resolution = plan.contoning_polygonize_color_regions_enabled ? TextureMappingZone::normalize_top_surface_contoning_polygonize_resolution(plan.contoning_polygonize_resolution) : 1; + key.surface_anchored_stack_optimizations = plan.contoning_surface_anchored_stack_optimizations_enabled; key.td_adjustment = plan.contoning_td_adjustment_enabled; key.surface_scatter = plan.contoning_surface_scatter_enabled; key.beer_lambert_rgb_correction = plan.contoning_beer_lambert_rgb_correction_enabled; @@ -3181,6 +3461,7 @@ static std::vector top_surface_image_conto area, plan.contoning_min_feature_mm, plan.contoning_polygonize_color_regions_enabled, + plan.contoning_surface_anchored_stack_optimizations_enabled, source_surface == TopSurfaceImageSourceSurface::Bottom && plan.contoning_td_adjustment_enabled, throw_if_canceled); @@ -3426,6 +3707,7 @@ static TopSurfaceImageContoningStackPlanKey top_surface_image_contoning_stack_pl key.polygonize_resolution = plan.contoning_polygonize_color_regions_enabled ? TextureMappingZone::normalize_top_surface_contoning_polygonize_resolution(plan.contoning_polygonize_resolution) : 1; + key.surface_anchored_stack_optimizations = plan.contoning_surface_anchored_stack_optimizations_enabled; key.td_adjustment = plan.contoning_td_adjustment_enabled; key.surface_scatter = plan.contoning_surface_scatter_enabled; key.beer_lambert_rgb_correction = plan.contoning_beer_lambert_rgb_correction_enabled; @@ -3513,6 +3795,7 @@ static std::vector top_surface_image_conto area, plan.contoning_min_feature_mm, plan.contoning_polygonize_color_regions_enabled, + plan.contoning_surface_anchored_stack_optimizations_enabled, source_surface == TopSurfaceImageSourceSurface::Bottom && plan.contoning_td_adjustment_enabled, throw_if_canceled); @@ -4108,6 +4391,9 @@ static std::vector top_surface_image_region_plans( TextureMappingZone::normalize_top_surface_contoning_polygonize_resolution(zone->top_surface_contoning_polygonize_resolution); plan.contoning_surface_anchored_stacks_enabled = zone->effective_top_surface_contoning_surface_anchored_stacks_enabled(); + plan.contoning_surface_anchored_stack_optimizations_enabled = + plan.contoning_surface_anchored_stacks_enabled && + zone->effective_top_surface_contoning_surface_anchored_stack_optimizations_enabled(); plan.contoning_beam_search_stack_expansion_enabled = zone->effective_top_surface_contoning_beam_search_stack_expansion_enabled(); plan.contoning_td_adjustment_enabled = zone->top_surface_contoning_td_adjustment_enabled; diff --git a/src/libslic3r/TextureMapping.cpp b/src/libslic3r/TextureMapping.cpp index 7d4a6cc669b..be3b421aa23 100644 --- a/src/libslic3r/TextureMapping.cpp +++ b/src/libslic3r/TextureMapping.cpp @@ -1163,6 +1163,8 @@ bool TextureMappingZone::operator==(const TextureMappingZone &rhs) const TextureMappingZone::normalize_top_surface_contoning_polygonize_resolution(top_surface_contoning_polygonize_resolution) == TextureMappingZone::normalize_top_surface_contoning_polygonize_resolution(rhs.top_surface_contoning_polygonize_resolution) && effective_top_surface_contoning_surface_anchored_stacks_enabled() == rhs.effective_top_surface_contoning_surface_anchored_stacks_enabled() && + effective_top_surface_contoning_surface_anchored_stack_optimizations_enabled() == + rhs.effective_top_surface_contoning_surface_anchored_stack_optimizations_enabled() && top_surface_contoning_td_adjustment_enabled == rhs.top_surface_contoning_td_adjustment_enabled && top_surface_contoning_surface_scatter_enabled == rhs.top_surface_contoning_surface_scatter_enabled && top_surface_contoning_beer_lambert_rgb_correction_enabled == rhs.top_surface_contoning_beer_lambert_rgb_correction_enabled && @@ -1570,6 +1572,8 @@ std::string TextureMappingManager::serialize_entries() TextureMappingZone::normalize_top_surface_contoning_polygonize_resolution(zone.top_surface_contoning_polygonize_resolution); texture["top_surface_contoning_surface_anchored_stacks_enabled"] = zone.effective_top_surface_contoning_surface_anchored_stacks_enabled(); + texture["top_surface_contoning_surface_anchored_stack_optimizations_enabled"] = + zone.effective_top_surface_contoning_surface_anchored_stack_optimizations_enabled(); texture["top_surface_contoning_td_adjustment_enabled"] = zone.top_surface_contoning_td_adjustment_enabled; texture["top_surface_contoning_surface_scatter_enabled"] = @@ -1879,6 +1883,9 @@ void TextureMappingManager::load_entries(const std::string &serialized, zone.top_surface_contoning_surface_anchored_stacks_enabled = texture.value("top_surface_contoning_surface_anchored_stacks_enabled", TextureMappingZone::DefaultTopSurfaceContoningSurfaceAnchoredStacksEnabled); + zone.top_surface_contoning_surface_anchored_stack_optimizations_enabled = + texture.value("top_surface_contoning_surface_anchored_stack_optimizations_enabled", + TextureMappingZone::DefaultTopSurfaceContoningSurfaceAnchoredStackOptimizationsEnabled); zone.top_surface_contoning_td_adjustment_enabled = texture.value("top_surface_contoning_td_adjustment_enabled", TextureMappingZone::DefaultTopSurfaceContoningTdAdjustmentEnabled); diff --git a/src/libslic3r/TextureMapping.hpp b/src/libslic3r/TextureMapping.hpp index 3e72b4a970a..f923a7aa2e1 100644 --- a/src/libslic3r/TextureMapping.hpp +++ b/src/libslic3r/TextureMapping.hpp @@ -201,6 +201,7 @@ struct TextureMappingZone static constexpr bool DefaultTopSurfaceContoningPolygonizeColorRegionsEnabled = true; static constexpr int DefaultTopSurfaceContoningPolygonizeResolution = 4; static constexpr bool DefaultTopSurfaceContoningSurfaceAnchoredStacksEnabled = false; + static constexpr bool DefaultTopSurfaceContoningSurfaceAnchoredStackOptimizationsEnabled = true; static constexpr bool DefaultTopSurfaceContoningTdAdjustmentEnabled = true; static constexpr bool DefaultTopSurfaceContoningSurfaceScatterEnabled = false; static constexpr bool DefaultTopSurfaceContoningBeerLambertRgbCorrectionEnabled = false; @@ -285,6 +286,11 @@ struct TextureMappingZone return ShowExperimentalTopSurfaceContoningOptions && value; } + static bool effective_top_surface_contoning_surface_anchored_stack_optimizations_enabled(bool value) + { + return ShowExperimentalTopSurfaceContoningOptions ? value : true; + } + static bool effective_top_surface_contoning_beam_search_stack_expansion_enabled(bool value) { return ShowExperimentalTopSurfaceContoningOptions ? value : true; @@ -401,6 +407,7 @@ struct TextureMappingZone bool top_surface_contoning_polygonize_color_regions_enabled = DefaultTopSurfaceContoningPolygonizeColorRegionsEnabled; int top_surface_contoning_polygonize_resolution = DefaultTopSurfaceContoningPolygonizeResolution; bool top_surface_contoning_surface_anchored_stacks_enabled = DefaultTopSurfaceContoningSurfaceAnchoredStacksEnabled; + bool top_surface_contoning_surface_anchored_stack_optimizations_enabled = DefaultTopSurfaceContoningSurfaceAnchoredStackOptimizationsEnabled; bool top_surface_contoning_td_adjustment_enabled = DefaultTopSurfaceContoningTdAdjustmentEnabled; bool top_surface_contoning_surface_scatter_enabled = DefaultTopSurfaceContoningSurfaceScatterEnabled; bool top_surface_contoning_beer_lambert_rgb_correction_enabled = DefaultTopSurfaceContoningBeerLambertRgbCorrectionEnabled; @@ -523,6 +530,12 @@ struct TextureMappingZone top_surface_contoning_surface_anchored_stacks_enabled); } + bool effective_top_surface_contoning_surface_anchored_stack_optimizations_enabled() const + { + return TextureMappingZone::effective_top_surface_contoning_surface_anchored_stack_optimizations_enabled( + top_surface_contoning_surface_anchored_stack_optimizations_enabled); + } + bool effective_top_surface_contoning_beam_search_stack_expansion_enabled() const { return TextureMappingZone::effective_top_surface_contoning_beam_search_stack_expansion_enabled( @@ -565,6 +578,7 @@ struct TextureMappingZone top_surface_contoning_perimeter_mode = DefaultTopSurfaceContoningPerimeterMode; top_surface_contoning_flat_surface_infill_mode = DefaultTopSurfaceContoningFlatSurfaceInfillMode; top_surface_contoning_surface_anchored_stacks_enabled = false; + top_surface_contoning_surface_anchored_stack_optimizations_enabled = true; top_surface_contoning_beam_search_stack_expansion_enabled = true; top_surface_contoning_layer_phase_enabled = false; top_surface_contoning_blue_noise_error_diffusion_enabled = false; @@ -638,6 +652,7 @@ struct TextureMappingZone top_surface_contoning_polygonize_color_regions_enabled = DefaultTopSurfaceContoningPolygonizeColorRegionsEnabled; top_surface_contoning_polygonize_resolution = DefaultTopSurfaceContoningPolygonizeResolution; top_surface_contoning_surface_anchored_stacks_enabled = DefaultTopSurfaceContoningSurfaceAnchoredStacksEnabled; + top_surface_contoning_surface_anchored_stack_optimizations_enabled = DefaultTopSurfaceContoningSurfaceAnchoredStackOptimizationsEnabled; top_surface_contoning_td_adjustment_enabled = DefaultTopSurfaceContoningTdAdjustmentEnabled; top_surface_contoning_surface_scatter_enabled = DefaultTopSurfaceContoningSurfaceScatterEnabled; top_surface_contoning_beer_lambert_rgb_correction_enabled = DefaultTopSurfaceContoningBeerLambertRgbCorrectionEnabled; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 4a61ae6926f..0bb144579e4 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2105,6 +2105,7 @@ public: bool top_surface_contoning_polygonize_color_regions_enabled, int top_surface_contoning_polygonize_resolution, bool top_surface_contoning_surface_anchored_stacks_enabled, + bool top_surface_contoning_surface_anchored_stack_optimizations_enabled, bool top_surface_contoning_beam_search_stack_expansion_enabled, bool top_surface_contoning_td_adjustment_enabled, bool top_surface_contoning_surface_scatter_enabled, @@ -2970,6 +2971,16 @@ public: 0, wxEXPAND | wxTOP | wxBOTTOM, gap / 2); + m_top_surface_contoning_surface_anchored_stack_optimizations_checkbox = + new wxCheckBox(m_top_surface_contoning_checkboxes_panel, wxID_ANY, _L("Surface-anchored stack optimizations")); + m_top_surface_contoning_surface_anchored_stack_optimizations_checkbox->SetValue( + top_surface_contoning_surface_anchored_stack_optimizations_enabled); + m_top_surface_contoning_surface_anchored_stack_optimizations_checkbox->SetMinSize( + wxSize(-1, std::max(m_top_surface_contoning_surface_anchored_stack_optimizations_checkbox->GetBestSize().GetHeight(), FromDIP(24)))); + contoning_checkboxes_root->Add(m_top_surface_contoning_surface_anchored_stack_optimizations_checkbox, + 0, + wxEXPAND | wxTOP | wxBOTTOM, + gap / 2); m_top_surface_contoning_beam_search_stack_expansion_checkbox = new wxCheckBox(m_top_surface_contoning_checkboxes_panel, wxID_ANY, _L("Use beam search for stack expansion")); m_top_surface_contoning_beam_search_stack_expansion_checkbox->SetValue(top_surface_contoning_beam_search_stack_expansion_enabled); @@ -3528,6 +3539,14 @@ public: TextureMappingZone::DefaultTopSurfaceContoningSurfaceAnchoredStacksEnabled : m_top_surface_contoning_surface_anchored_stacks_checkbox->GetValue(); } + bool top_surface_contoning_surface_anchored_stack_optimizations_enabled() const + { + if (!TextureMappingZone::ShowExperimentalTopSurfaceContoningOptions) + return true; + return m_top_surface_contoning_surface_anchored_stack_optimizations_checkbox == nullptr ? + TextureMappingZone::DefaultTopSurfaceContoningSurfaceAnchoredStackOptimizationsEnabled : + m_top_surface_contoning_surface_anchored_stack_optimizations_checkbox->GetValue(); + } bool top_surface_contoning_beam_search_stack_expansion_enabled() const { if (!TextureMappingZone::ShowExperimentalTopSurfaceContoningOptions) @@ -4447,6 +4466,10 @@ private: m_top_surface_contoning_surface_anchored_stacks_checkbox->Show(contoning); m_top_surface_contoning_surface_anchored_stacks_checkbox->Enable(contoning); } + if (m_top_surface_contoning_surface_anchored_stack_optimizations_checkbox != nullptr) { + m_top_surface_contoning_surface_anchored_stack_optimizations_checkbox->Show(contoning); + m_top_surface_contoning_surface_anchored_stack_optimizations_checkbox->Enable(contoning && surface_anchored_stacks); + } if (m_top_surface_contoning_beam_search_stack_expansion_checkbox != nullptr) { m_top_surface_contoning_beam_search_stack_expansion_checkbox->Show(contoning); m_top_surface_contoning_beam_search_stack_expansion_checkbox->Enable(contoning); @@ -4540,6 +4563,7 @@ private: wxPanel *m_top_surface_contoning_polygonize_resolution_panel {nullptr}; wxChoice *m_top_surface_contoning_polygonize_resolution_choice {nullptr}; wxCheckBox *m_top_surface_contoning_surface_anchored_stacks_checkbox {nullptr}; + wxCheckBox *m_top_surface_contoning_surface_anchored_stack_optimizations_checkbox {nullptr}; wxCheckBox *m_top_surface_contoning_beam_search_stack_expansion_checkbox {nullptr}; wxCheckBox *m_top_surface_contoning_td_adjustment_checkbox {nullptr}; wxCheckBox *m_top_surface_contoning_surface_scatter_checkbox {nullptr}; @@ -9574,6 +9598,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager) updated.top_surface_contoning_polygonize_color_regions_enabled, updated.top_surface_contoning_polygonize_resolution, updated.top_surface_contoning_surface_anchored_stacks_enabled, + updated.top_surface_contoning_surface_anchored_stack_optimizations_enabled, updated.top_surface_contoning_beam_search_stack_expansion_enabled, updated.top_surface_contoning_td_adjustment_enabled, updated.top_surface_contoning_surface_scatter_enabled, @@ -9655,6 +9680,8 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager) dlg.top_surface_contoning_polygonize_resolution(); updated.top_surface_contoning_surface_anchored_stacks_enabled = dlg.top_surface_contoning_surface_anchored_stacks_enabled(); + updated.top_surface_contoning_surface_anchored_stack_optimizations_enabled = + dlg.top_surface_contoning_surface_anchored_stack_optimizations_enabled(); updated.top_surface_contoning_beam_search_stack_expansion_enabled = dlg.top_surface_contoning_beam_search_stack_expansion_enabled(); updated.top_surface_contoning_td_adjustment_enabled =