From 5accfa52eaac4a949c68c6ffee8c0aee67e6c91a Mon Sep 17 00:00:00 2001 From: sentientstardust Date: Sat, 30 May 2026 15:57:05 +0100 Subject: [PATCH] Use beam search for stack expansion. Move experimental contoning option flag to cpp file to reduce recompilation time --- src/libslic3r/ColorSolver.cpp | 164 +++++++++++++++++++- src/libslic3r/ColorSolver.hpp | 9 +- src/libslic3r/Fill/Fill.cpp | 7 + src/libslic3r/TextureMapping.cpp | 8 + src/libslic3r/TextureMapping.hpp | 46 ++++-- src/libslic3r/TextureMappingContoning.cpp | 4 +- src/libslic3r/TextureMappingContoning.hpp | 1 + src/slic3r/GUI/MMUPaintedTexturePreview.cpp | 9 +- src/slic3r/GUI/Plater.cpp | 26 ++++ 9 files changed, 247 insertions(+), 27 deletions(-) diff --git a/src/libslic3r/ColorSolver.cpp b/src/libslic3r/ColorSolver.cpp index 37b2ea57cd6..3c7677a5a6a 100644 --- a/src/libslic3r/ColorSolver.cpp +++ b/src/libslic3r/ColorSolver.cpp @@ -823,6 +823,150 @@ std::vector> stretched_ordered_stack_variants(const std::v return variants; } +struct OrderedStackExpansionBeamState { + std::vector stack; + size_t next_control_idx { 0 }; + float score { 0.f }; +}; + +int ordered_stack_run_length(const std::vector &stack, uint16_t component) +{ + int run = 0; + for (auto it = stack.rbegin(); it != stack.rend() && *it == component; ++it) + ++run; + return run; +} + +float ordered_stack_beam_transition_score(const std::vector &control, + const std::vector &layer_opacities, + const OrderedStackExpansionBeamState &state, + uint16_t component, + bool consume, + int stack_depth) +{ + const int slot = int(state.stack.size()); + const float control_pos = + stack_depth > 0 ? + ((float(slot) + 0.5f) * float(control.size()) / float(stack_depth) - 0.5f) : + float(state.next_control_idx); + const float layout_penalty = std::abs(float(state.next_control_idx) - control_pos); + const float depth_t = + stack_depth > 1 ? + std::clamp(float(slot) / float(stack_depth - 1), 0.f, 1.f) : + 0.f; + const size_t component_idx = size_t(component); + const float layer_opacity = + component_idx < layer_opacities.size() && std::isfinite(layer_opacities[component_idx]) ? + std::clamp(layer_opacities[component_idx], 1e-4f, 0.9999f) : + 0.5f; + const float transmission = 1.f - layer_opacity; + const int run = ordered_stack_run_length(state.stack, component); + + float score = -0.55f * layout_penalty; + if (!consume) + score += 0.20f * transmission + 0.12f * depth_t - 0.10f * (1.f - depth_t); + else + score += 0.02f; + if (run > 0) + score -= (0.12f + 0.30f * (1.f - depth_t)) * float(std::min(run, 5)); + return score; +} + +void prune_ordered_stack_expansion_beam(std::vector &states, size_t beam_width) +{ + std::sort(states.begin(), states.end(), [](const OrderedStackExpansionBeamState &lhs, + const OrderedStackExpansionBeamState &rhs) { + return lhs.score > rhs.score; + }); + std::vector pruned; + pruned.reserve(std::min(states.size(), beam_width)); + for (OrderedStackExpansionBeamState &state : states) { + const bool duplicate = + std::any_of(pruned.begin(), pruned.end(), [&state](const OrderedStackExpansionBeamState &existing) { + return existing.next_control_idx == state.next_control_idx && existing.stack == state.stack; + }); + if (duplicate) + continue; + pruned.emplace_back(std::move(state)); + if (pruned.size() >= beam_width) + break; + } + states = std::move(pruned); +} + +std::vector> beam_stretched_ordered_stack_variants(const std::vector &control, + const std::vector &layer_opacities, + int stack_depth, + size_t variant_limit) +{ + std::vector> variants; + if (control.empty() || stack_depth <= 0 || variant_limit == 0) + return variants; + if (int(control.size()) >= stack_depth) { + std::vector variant(control.begin(), control.begin() + std::min(control.size(), size_t(stack_depth))); + append_unique_ordered_stack_variant(variants, std::move(variant)); + return variants; + } + + const size_t beam_width = std::max(variant_limit, std::min(32, variant_limit * 2)); + std::vector beam(1); + beam.front().stack.reserve(size_t(stack_depth)); + + for (int slot = 0; slot < stack_depth; ++slot) { + std::vector next; + next.reserve(beam.size() * 2); + for (const OrderedStackExpansionBeamState &state : beam) { + if (state.next_control_idx >= control.size()) + continue; + const uint16_t component = control[state.next_control_idx]; + const int remaining_slots = stack_depth - slot - 1; + const int remaining_after_consume = int(control.size() - state.next_control_idx - 1); + if (remaining_slots >= remaining_after_consume) { + OrderedStackExpansionBeamState consumed = state; + consumed.stack.emplace_back(component); + consumed.score += ordered_stack_beam_transition_score(control, layer_opacities, state, component, true, stack_depth); + ++consumed.next_control_idx; + next.emplace_back(std::move(consumed)); + } + + const int remaining_after_duplicate = int(control.size() - state.next_control_idx); + if (remaining_slots >= remaining_after_duplicate) { + OrderedStackExpansionBeamState duplicated = state; + duplicated.stack.emplace_back(component); + duplicated.score += ordered_stack_beam_transition_score(control, layer_opacities, state, component, false, stack_depth); + next.emplace_back(std::move(duplicated)); + } + } + if (next.empty()) + break; + prune_ordered_stack_expansion_beam(next, beam_width); + beam = std::move(next); + } + + std::sort(beam.begin(), beam.end(), [](const OrderedStackExpansionBeamState &lhs, + const OrderedStackExpansionBeamState &rhs) { + return lhs.score > rhs.score; + }); + for (OrderedStackExpansionBeamState &state : beam) { + if (state.next_control_idx != control.size() || int(state.stack.size()) != stack_depth) + continue; + append_unique_ordered_stack_variant(variants, std::move(state.stack)); + if (variants.size() >= variant_limit) + break; + } + + if (variants.size() < variant_limit) { + std::vector> fallback = + stretched_ordered_stack_variants(control, layer_opacities, stack_depth); + for (std::vector &variant : fallback) { + append_unique_ordered_stack_variant(variants, std::move(variant)); + if (variants.size() >= variant_limit) + break; + } + } + return variants; +} + void append_ordered_stack_candidate(ColorSolverOrderedStackCandidateSet &candidates, const std::vector> &colors_with_background, std::vector &weights, @@ -1081,7 +1225,8 @@ std::string color_solver_ordered_stack_candidate_cache_key(const std::vector &component_roles) + const std::vector &component_roles, + bool beam_search_stack_expansion) { std::ostringstream key; key << component_colors.size(); @@ -1095,6 +1240,7 @@ std::string color_solver_ordered_stack_candidate_cache_key(const std::vector &component_roles) + const std::vector &component_roles, + bool beam_search_stack_expansion) { ColorSolverOrderedStackCandidateSet candidates; int simulated_depth = simulated_stack_depth > 0 ? simulated_stack_depth : stack_depth; @@ -1212,7 +1359,9 @@ ColorSolverOrderedStackCandidateSet build_color_solver_ordered_stack_candidates( return; if (depth_idx == control_depth) { std::vector> variants = - stretched_ordered_stack_variants(control, layer_opacities, stack_depth); + beam_search_stack_expansion ? + beam_stretched_ordered_stack_variants(control, layer_opacities, stack_depth, variant_budget) : + stretched_ordered_stack_variants(control, layer_opacities, stack_depth); for (const std::vector &surface_to_deep : variants) { if (candidates.rgbs.size() / 3 >= max_candidate_count) { limit_reached = true; @@ -1258,7 +1407,8 @@ const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates float surface_scatter, bool beer_lambert_rgb_correction, bool td_effective_alpha_correction, - const std::vector &component_roles) + const std::vector &component_roles, + bool beam_search_stack_expansion) { const std::string key = color_solver_ordered_stack_candidate_cache_key(component_colors, @@ -1272,7 +1422,8 @@ const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates surface_scatter, beer_lambert_rgb_correction, td_effective_alpha_correction, - component_roles); + component_roles, + beam_search_stack_expansion); auto it = cache.find(key); if (it != cache.end()) return it->second; @@ -1289,7 +1440,8 @@ const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates surface_scatter, beer_lambert_rgb_correction, td_effective_alpha_correction, - component_roles)).first->second; + component_roles, + beam_search_stack_expansion)).first->second; } std::vector solve_color_solver_ordered_stack_for_target( diff --git a/src/libslic3r/ColorSolver.hpp b/src/libslic3r/ColorSolver.hpp index 0ae219f004a..74379502fca 100644 --- a/src/libslic3r/ColorSolver.hpp +++ b/src/libslic3r/ColorSolver.hpp @@ -153,7 +153,8 @@ std::string color_solver_ordered_stack_candidate_cache_key(const std::vector &component_roles = {}); + const std::vector &component_roles = {}, + bool beam_search_stack_expansion = false); ColorSolverOrderedStackCandidateSet build_color_solver_ordered_stack_candidates( const std::vector> &component_colors, const std::vector &layer_opacities, @@ -166,7 +167,8 @@ ColorSolverOrderedStackCandidateSet build_color_solver_ordered_stack_candidates( float surface_scatter = 0.f, bool beer_lambert_rgb_correction = false, bool td_effective_alpha_correction = false, - const std::vector &component_roles = {}); + const std::vector &component_roles = {}, + bool beam_search_stack_expansion = false); const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates( ColorSolverOrderedStackCandidateCache &cache, const std::vector> &component_colors, @@ -180,7 +182,8 @@ const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates float surface_scatter = 0.f, bool beer_lambert_rgb_correction = false, bool td_effective_alpha_correction = false, - const std::vector &component_roles = {}); + const std::vector &component_roles = {}, + bool beam_search_stack_expansion = false); std::vector solve_color_solver_ordered_stack_for_target( const ColorSolverOrderedStackCandidateSet &candidates, const std::array &target_rgb, diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 8ae6ad50f6f..7c78bf22c6f 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -508,6 +508,7 @@ struct TopSurfaceImageRegionPlan { bool contoning_surface_scatter_enabled = TextureMappingZone::DefaultTopSurfaceContoningSurfaceScatterEnabled; bool contoning_beer_lambert_rgb_correction_enabled = TextureMappingZone::DefaultTopSurfaceContoningBeerLambertRgbCorrectionEnabled; bool contoning_td_effective_alpha_correction_enabled = TextureMappingZone::DefaultTopSurfaceContoningTdEffectiveAlphaCorrectionEnabled; + bool contoning_beam_search_stack_expansion_enabled = TextureMappingZone::DefaultTopSurfaceContoningBeamSearchStackExpansionEnabled; int contoning_generic_solver_mix_model = TextureMappingZone::DefaultGenericSolverMixModel; int contoning_flat_surface_infill_mode = TextureMappingZone::SlicerDefaultTopSurfaceContoningFlatSurfaceInfillMode; }; @@ -1178,6 +1179,7 @@ struct TopSurfaceImageContoningStackPlanKey { bool surface_scatter { false }; bool beer_lambert_rgb_correction { false }; bool td_effective_alpha_correction { false }; + bool beam_search_stack_expansion { false }; int mix_model { TextureMappingZone::DefaultGenericSolverMixModel }; bool operator<(const TopSurfaceImageContoningStackPlanKey &rhs) const @@ -1210,6 +1212,7 @@ struct TopSurfaceImageContoningStackPlanKey { surface_scatter, beer_lambert_rgb_correction, td_effective_alpha_correction, + beam_search_stack_expansion, mix_model) < std::tie(rhs.source_layer, rhs.source_layer_id, @@ -1239,6 +1242,7 @@ struct TopSurfaceImageContoningStackPlanKey { rhs.surface_scatter, rhs.beer_lambert_rgb_correction, rhs.td_effective_alpha_correction, + rhs.beam_search_stack_expansion, rhs.mix_model); } }; @@ -2645,6 +2649,7 @@ static TopSurfaceImageContoningStackPlanKey top_surface_image_contoning_stack_pl key.surface_scatter = plan.contoning_surface_scatter_enabled; key.beer_lambert_rgb_correction = plan.contoning_beer_lambert_rgb_correction_enabled; key.td_effective_alpha_correction = plan.contoning_td_effective_alpha_correction_enabled; + key.beam_search_stack_expansion = plan.contoning_beam_search_stack_expansion_enabled; key.mix_model = plan.contoning_generic_solver_mix_model; return key; } @@ -3308,6 +3313,8 @@ 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_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; plan.contoning_surface_scatter_enabled = plan.contoning_td_adjustment_enabled && zone->top_surface_contoning_surface_scatter_enabled; diff --git a/src/libslic3r/TextureMapping.cpp b/src/libslic3r/TextureMapping.cpp index bf4c357b04f..7d4a6cc669b 100644 --- a/src/libslic3r/TextureMapping.cpp +++ b/src/libslic3r/TextureMapping.cpp @@ -17,6 +17,8 @@ namespace Slic3r { +const bool TextureMappingZone::ShowExperimentalTopSurfaceContoningOptions = false; + namespace { constexpr unsigned int TextureMappingZoneIdBase = 99; @@ -1165,6 +1167,7 @@ bool TextureMappingZone::operator==(const TextureMappingZone &rhs) const 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 && top_surface_contoning_td_effective_alpha_correction_enabled == rhs.top_surface_contoning_td_effective_alpha_correction_enabled && + effective_top_surface_contoning_beam_search_stack_expansion_enabled() == rhs.effective_top_surface_contoning_beam_search_stack_expansion_enabled() && compact_offset_mode == rhs.compact_offset_mode && use_legacy_fixed_color_mode == rhs.use_legacy_fixed_color_mode && high_speed_image_texture_sampling == rhs.high_speed_image_texture_sampling && @@ -1575,6 +1578,8 @@ std::string TextureMappingManager::serialize_entries() zone.top_surface_contoning_beer_lambert_rgb_correction_enabled; texture["top_surface_contoning_td_effective_alpha_correction_enabled"] = zone.top_surface_contoning_td_effective_alpha_correction_enabled; + texture["top_surface_contoning_beam_search_stack_expansion_enabled"] = + zone.effective_top_surface_contoning_beam_search_stack_expansion_enabled(); texture["compact_offset_mode"] = zone.compact_offset_mode; texture["use_legacy_fixed_color_mode"] = zone.use_legacy_fixed_color_mode; texture["high_speed_image_texture_sampling"] = true; @@ -1886,6 +1891,9 @@ void TextureMappingManager::load_entries(const std::string &serialized, zone.top_surface_contoning_td_effective_alpha_correction_enabled = texture.value("top_surface_contoning_td_effective_alpha_correction_enabled", TextureMappingZone::DefaultTopSurfaceContoningTdEffectiveAlphaCorrectionEnabled); + zone.top_surface_contoning_beam_search_stack_expansion_enabled = + texture.value("top_surface_contoning_beam_search_stack_expansion_enabled", + TextureMappingZone::DefaultTopSurfaceContoningBeamSearchStackExpansionEnabled); zone.apply_top_surface_contoning_experimental_defaults(); zone.compact_offset_mode = texture.value("compact_offset_mode", TextureMappingZone::DefaultCompactOffsetMode); zone.use_legacy_fixed_color_mode = diff --git a/src/libslic3r/TextureMapping.hpp b/src/libslic3r/TextureMapping.hpp index 01a4ec03481..4ffb32006df 100644 --- a/src/libslic3r/TextureMapping.hpp +++ b/src/libslic3r/TextureMapping.hpp @@ -3,10 +3,6 @@ #ifndef slic3r_TextureMapping_hpp_ #define slic3r_TextureMapping_hpp_ -#ifndef SLIC3R_SHOW_EXPERIMENTAL_CONTONING_OPTIONS -#define SLIC3R_SHOW_EXPERIMENTAL_CONTONING_OPTIONS 0 -#endif - #include #include #include @@ -208,6 +204,8 @@ struct TextureMappingZone static constexpr bool DefaultTopSurfaceContoningTdAdjustmentEnabled = true; static constexpr bool DefaultTopSurfaceContoningSurfaceScatterEnabled = false; static constexpr bool DefaultTopSurfaceContoningBeerLambertRgbCorrectionEnabled = false; + static constexpr bool DefaultTopSurfaceContoningTdEffectiveAlphaCorrectionEnabled = true; + static constexpr bool DefaultTopSurfaceContoningBeamSearchStackExpansionEnabled = true; static constexpr bool DefaultCompactOffsetMode = true; static constexpr bool DefaultUseLegacyFixedColorMode = false; static constexpr bool DefaultHighSpeedImageTextureSampling = true; @@ -232,7 +230,7 @@ struct TextureMappingZone static constexpr bool DefaultPreviewLimitResolution = true; static constexpr bool DefaultPreviewSimulateTopSurfaceLod = true; static constexpr bool DefaultAutoAdjustFilamentSelection = true; - static constexpr bool ShowExperimentalTopSurfaceContoningOptions = SLIC3R_SHOW_EXPERIMENTAL_CONTONING_OPTIONS != 0; + static const bool ShowExperimentalTopSurfaceContoningOptions; static constexpr int default_modulation_mode_for_surface_pattern(int surface_pattern) { @@ -243,7 +241,7 @@ struct TextureMappingZone } } - static constexpr int effective_top_surface_contoning_flat_surface_infill_mode(int mode) + static int effective_top_surface_contoning_flat_surface_infill_mode(int mode) { if (!ShowExperimentalTopSurfaceContoningOptions) return SlicerDefaultTopSurfaceContoningFlatSurfaceInfillMode; @@ -252,52 +250,57 @@ struct TextureMappingZone mode; } - static constexpr int stored_top_surface_contoning_flat_surface_infill_mode(int mode) + static int stored_top_surface_contoning_flat_surface_infill_mode(int mode) { return ShowExperimentalTopSurfaceContoningOptions ? mode : DefaultTopSurfaceContoningFlatSurfaceInfillMode; } - static constexpr int stored_top_surface_contoning_perimeter_mode(int mode) + static int stored_top_surface_contoning_perimeter_mode(int mode) { return ShowExperimentalTopSurfaceContoningOptions ? mode : DefaultTopSurfaceContoningPerimeterMode; } - static constexpr float effective_top_surface_contoning_angle_threshold_deg(float value) + static float effective_top_surface_contoning_angle_threshold_deg(float value) { return ShowExperimentalTopSurfaceContoningOptions ? value : MaxTopSurfaceContoningAngleThresholdDeg; } - static constexpr bool effective_top_surface_contoning_only_color_surface_infill(bool value) + static bool effective_top_surface_contoning_only_color_surface_infill(bool value) { return ShowExperimentalTopSurfaceContoningOptions ? value : true; } - static constexpr bool effective_top_surface_contoning_replace_top_perimeters_with_infill(bool value) + static bool effective_top_surface_contoning_replace_top_perimeters_with_infill(bool value) { return ShowExperimentalTopSurfaceContoningOptions && value; } - static constexpr bool effective_top_surface_contoning_recolor_surrounding_perimeters(bool value, bool replace) + static bool effective_top_surface_contoning_recolor_surrounding_perimeters(bool value, bool replace) { return ShowExperimentalTopSurfaceContoningOptions && value && !replace; } - static constexpr bool effective_top_surface_contoning_surface_anchored_stacks_enabled(bool value) + static bool effective_top_surface_contoning_surface_anchored_stacks_enabled(bool value) { return ShowExperimentalTopSurfaceContoningOptions && value; } - static constexpr bool effective_top_surface_contoning_layer_phase_enabled(bool value) + static bool effective_top_surface_contoning_beam_search_stack_expansion_enabled(bool value) + { + return ShowExperimentalTopSurfaceContoningOptions ? value : true; + } + + static bool effective_top_surface_contoning_layer_phase_enabled(bool value) { return ShowExperimentalTopSurfaceContoningOptions && value; } - static constexpr bool effective_top_surface_contoning_blue_noise_error_diffusion_enabled(bool value) + static bool effective_top_surface_contoning_blue_noise_error_diffusion_enabled(bool value) { return ShowExperimentalTopSurfaceContoningOptions && value; } - static constexpr bool effective_top_surface_contoning_supersampled_cells_enabled(bool value) + static bool effective_top_surface_contoning_supersampled_cells_enabled(bool value) { return ShowExperimentalTopSurfaceContoningOptions && value; } @@ -389,6 +392,8 @@ struct TextureMappingZone 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; + bool top_surface_contoning_td_effective_alpha_correction_enabled = DefaultTopSurfaceContoningTdEffectiveAlphaCorrectionEnabled; + bool top_surface_contoning_beam_search_stack_expansion_enabled = DefaultTopSurfaceContoningBeamSearchStackExpansionEnabled; bool compact_offset_mode = DefaultCompactOffsetMode; bool use_legacy_fixed_color_mode = DefaultUseLegacyFixedColorMode; bool high_speed_image_texture_sampling = DefaultHighSpeedImageTextureSampling; @@ -506,6 +511,12 @@ struct TextureMappingZone top_surface_contoning_surface_anchored_stacks_enabled); } + bool effective_top_surface_contoning_beam_search_stack_expansion_enabled() const + { + return TextureMappingZone::effective_top_surface_contoning_beam_search_stack_expansion_enabled( + top_surface_contoning_beam_search_stack_expansion_enabled); + } + bool effective_top_surface_contoning_layer_phase_enabled() const { return TextureMappingZone::effective_top_surface_contoning_layer_phase_enabled( @@ -540,6 +551,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_beam_search_stack_expansion_enabled = true; top_surface_contoning_layer_phase_enabled = false; top_surface_contoning_blue_noise_error_diffusion_enabled = false; top_surface_contoning_supersampled_cells_enabled = false; @@ -611,6 +623,8 @@ struct TextureMappingZone top_surface_contoning_td_adjustment_enabled = DefaultTopSurfaceContoningTdAdjustmentEnabled; top_surface_contoning_surface_scatter_enabled = DefaultTopSurfaceContoningSurfaceScatterEnabled; top_surface_contoning_beer_lambert_rgb_correction_enabled = DefaultTopSurfaceContoningBeerLambertRgbCorrectionEnabled; + top_surface_contoning_td_effective_alpha_correction_enabled = DefaultTopSurfaceContoningTdEffectiveAlphaCorrectionEnabled; + top_surface_contoning_beam_search_stack_expansion_enabled = DefaultTopSurfaceContoningBeamSearchStackExpansionEnabled; compact_offset_mode = DefaultCompactOffsetMode; use_legacy_fixed_color_mode = DefaultUseLegacyFixedColorMode; high_speed_image_texture_sampling = DefaultHighSpeedImageTextureSampling; diff --git a/src/libslic3r/TextureMappingContoning.cpp b/src/libslic3r/TextureMappingContoning.cpp index 5d5fec962c1..329b59849f4 100644 --- a/src/libslic3r/TextureMappingContoning.cpp +++ b/src/libslic3r/TextureMappingContoning.cpp @@ -413,6 +413,7 @@ TextureMappingContoningSolver::TextureMappingContoningSolver(const TextureMappin m_td_adjustment_enabled && !m_td_effective_alpha_correction_enabled && zone.top_surface_contoning_beer_lambert_rgb_correction_enabled; + m_beam_search_stack_expansion_enabled = zone.effective_top_surface_contoning_beam_search_stack_expansion_enabled(); m_layer_height_mm = std::isfinite(layer_height_mm) && layer_height_mm > 0.f ? layer_height_mm : 0.2f; if (!std::isfinite(m_layer_height_mm) || m_layer_height_mm <= 0.f) m_layer_height_mm = 0.2f; @@ -652,7 +653,8 @@ TextureMappingContoningStack TextureMappingContoningSolver::solve(const std::arr m_surface_scatter, m_beer_lambert_rgb_correction_enabled, m_td_effective_alpha_correction_enabled, - m_component_roles); + m_component_roles, + m_beam_search_stack_expansion_enabled); } const std::vector surface_to_deep = solve_color_solver_ordered_stack_for_target(*ordered_candidates, target_rgb, ColorSolverMode::V2); diff --git a/src/libslic3r/TextureMappingContoning.hpp b/src/libslic3r/TextureMappingContoning.hpp index 484965c017d..6acc83f6c1d 100644 --- a/src/libslic3r/TextureMappingContoning.hpp +++ b/src/libslic3r/TextureMappingContoning.hpp @@ -70,6 +70,7 @@ private: bool m_td_adjustment_enabled { false }; bool m_beer_lambert_rgb_correction_enabled { false }; bool m_td_effective_alpha_correction_enabled { false }; + bool m_beam_search_stack_expansion_enabled { false }; std::vector m_component_roles; mutable std::map> m_candidates_by_depth; mutable std::shared_ptr m_ordered_candidate_cache { std::make_shared() }; diff --git a/src/slic3r/GUI/MMUPaintedTexturePreview.cpp b/src/slic3r/GUI/MMUPaintedTexturePreview.cpp index 3402b9914fc..51f65857dda 100644 --- a/src/slic3r/GUI/MMUPaintedTexturePreview.cpp +++ b/src/slic3r/GUI/MMUPaintedTexturePreview.cpp @@ -98,6 +98,7 @@ struct TexturePreviewSimulationSettings bool contoning_flat_surface_td_adjustment = false; bool contoning_flat_surface_beer_lambert_rgb_correction = false; bool contoning_flat_surface_td_effective_alpha_correction = false; + bool contoning_flat_surface_beam_search_stack_expansion = false; int contoning_flat_surface_pattern_filaments = TextureMappingZone::DefaultTopSurfaceContoningPatternFilaments; bool simulate_top_surface_lod = false; float top_surface_lod_pitch_mm = 0.f; @@ -2689,6 +2690,8 @@ std::optional texture_preview_simulation_setti settings.contoning_flat_surface_td_effective_alpha_correction = settings.contoning_flat_surface_td_adjustment && zone->top_surface_contoning_td_effective_alpha_correction_enabled; + settings.contoning_flat_surface_beam_search_stack_expansion = + zone->effective_top_surface_contoning_beam_search_stack_expansion_enabled(); settings.contoning_flat_surface_surface_scatter = settings.contoning_flat_surface_td_adjustment && zone->top_surface_contoning_surface_scatter_enabled ? @@ -2791,6 +2794,7 @@ size_t texture_preview_simulation_signature(const ModelVolume &model_volume, mix(std::hash{}(settings.contoning_flat_surface_td_adjustment ? 1 : 0)); mix(std::hash{}(settings.contoning_flat_surface_beer_lambert_rgb_correction ? 1 : 0)); mix(std::hash{}(settings.contoning_flat_surface_td_effective_alpha_correction ? 1 : 0)); + mix(std::hash{}(settings.contoning_flat_surface_beam_search_stack_expansion ? 1 : 0)); if (settings.contoning_flat_surface_quantization) { mix(std::hash{}(settings.contoning_flat_surface_pattern_filaments)); mix(std::hash{}(settings.simulate_top_surface_lod ? 1 : 0)); @@ -2896,7 +2900,8 @@ TexturePreviewSimulationResult build_simulated_texture_preview_result(size_t sig settings.contoning_flat_surface_surface_scatter, settings.contoning_flat_surface_beer_lambert_rgb_correction, settings.contoning_flat_surface_td_effective_alpha_correction, - settings.component_roles) : + settings.component_roles, + settings.contoning_flat_surface_beam_search_stack_expansion) : ColorSolverOrderedStackCandidateSet{}; const std::vector contoning_flat_surface_candidates = use_contoning_flat_surface_quantization && contoning_flat_surface_ordered_candidates.empty() ? @@ -5712,6 +5717,7 @@ static size_t texture_preview_settings_signature_impl(size_t num_physical, signature_mix(std::hash{}(zone.top_surface_contoning_surface_scatter_enabled ? 1 : 0)); signature_mix(std::hash{}(zone.top_surface_contoning_beer_lambert_rgb_correction_enabled ? 1 : 0)); signature_mix(std::hash{}(zone.top_surface_contoning_td_effective_alpha_correction_enabled ? 1 : 0)); + signature_mix(std::hash{}(zone.effective_top_surface_contoning_beam_search_stack_expansion_enabled() ? 1 : 0)); signature_mix(std::hash{}(zone.nonlinear_offset_adjustment ? 1 : 0)); signature_mix(std::hash{}(zone.compact_offset_mode ? 1 : 0)); signature_mix(std::hash{}(zone.use_legacy_fixed_color_mode ? 1 : 0)); @@ -5868,6 +5874,7 @@ static void texture_preview_mix_zone_baked_model_settings(size_t &signature, signature_mix(std::hash{}(zone.top_surface_contoning_surface_scatter_enabled ? 1 : 0)); signature_mix(std::hash{}(zone.top_surface_contoning_beer_lambert_rgb_correction_enabled ? 1 : 0)); signature_mix(std::hash{}(zone.top_surface_contoning_td_effective_alpha_correction_enabled ? 1 : 0)); + signature_mix(std::hash{}(zone.effective_top_surface_contoning_beam_search_stack_expansion_enabled() ? 1 : 0)); signature_mix(std::hash{}(zone.nonlinear_offset_adjustment ? 1 : 0)); signature_mix(std::hash{}(zone.compact_offset_mode ? 1 : 0)); signature_mix(std::hash{}(zone.use_legacy_fixed_color_mode ? 1 : 0)); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2f946062434..87126e064f5 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_beam_search_stack_expansion_enabled, bool top_surface_contoning_td_adjustment_enabled, bool top_surface_contoning_surface_scatter_enabled, bool top_surface_contoning_beer_lambert_rgb_correction_enabled, @@ -2969,6 +2970,15 @@ public: 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); + m_top_surface_contoning_beam_search_stack_expansion_checkbox->SetMinSize( + wxSize(-1, std::max(m_top_surface_contoning_beam_search_stack_expansion_checkbox->GetBestSize().GetHeight(), FromDIP(24)))); + contoning_checkboxes_root->Add(m_top_surface_contoning_beam_search_stack_expansion_checkbox, + 0, + wxEXPAND | wxTOP | wxBOTTOM, + gap / 2); } top_surface_box->Add(m_top_surface_contoning_checkboxes_panel, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP | wxBOTTOM, gap); if (m_top_surface_contoning_only_color_surface_infill_checkbox != nullptr) { @@ -3509,6 +3519,14 @@ public: TextureMappingZone::DefaultTopSurfaceContoningSurfaceAnchoredStacksEnabled : m_top_surface_contoning_surface_anchored_stacks_checkbox->GetValue(); } + bool top_surface_contoning_beam_search_stack_expansion_enabled() const + { + if (!TextureMappingZone::ShowExperimentalTopSurfaceContoningOptions) + return true; + return m_top_surface_contoning_beam_search_stack_expansion_checkbox == nullptr ? + TextureMappingZone::DefaultTopSurfaceContoningBeamSearchStackExpansionEnabled : + m_top_surface_contoning_beam_search_stack_expansion_checkbox->GetValue(); + } bool top_surface_contoning_td_adjustment_enabled() const { return m_top_surface_contoning_td_adjustment_checkbox == nullptr ? @@ -4410,6 +4428,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_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); + } if (m_top_surface_image_fixed_coloring_filaments_checkbox != nullptr) { m_top_surface_image_fixed_coloring_filaments_checkbox->Show(!contoning_selected); m_top_surface_image_fixed_coloring_filaments_checkbox->Enable(enabled && !contoning_selected); @@ -4499,6 +4521,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_beam_search_stack_expansion_checkbox {nullptr}; wxCheckBox *m_top_surface_contoning_td_adjustment_checkbox {nullptr}; wxCheckBox *m_top_surface_contoning_surface_scatter_checkbox {nullptr}; wxCheckBox *m_top_surface_contoning_beer_lambert_rgb_correction_checkbox {nullptr}; @@ -9532,6 +9555,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_beam_search_stack_expansion_enabled, updated.top_surface_contoning_td_adjustment_enabled, updated.top_surface_contoning_surface_scatter_enabled, updated.top_surface_contoning_beer_lambert_rgb_correction_enabled, @@ -9612,6 +9636,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_beam_search_stack_expansion_enabled = + dlg.top_surface_contoning_beam_search_stack_expansion_enabled(); updated.top_surface_contoning_td_adjustment_enabled = dlg.top_surface_contoning_td_adjustment_enabled(); updated.top_surface_contoning_surface_scatter_enabled =