Add variable layer height compensation mode. Tweak top-surface coloring UI

This commit is contained in:
sentientstardust
2026-05-31 16:59:03 +01:00
parent 63bc97e9ee
commit e9fe58b348
8 changed files with 411 additions and 141 deletions

View File

@@ -553,10 +553,28 @@ std::array<float, 3> td_effective_alpha_transmission(const std::array<float, 3>
return transmission_from_density_bias(td_effective_alpha_density_bias(srgb_color, role), scalar_transmission);
}
float ordered_stack_layer_opacity(const std::vector<float> &layer_opacities,
const std::vector<float> &layer_opacities_by_depth,
size_t component_count,
size_t depth_idx,
uint16_t component_idx)
{
const size_t component = size_t(component_idx);
const size_t depth_opacity_idx = depth_idx * component_count + component;
if (component_count > 0 &&
depth_opacity_idx < layer_opacities_by_depth.size() &&
std::isfinite(layer_opacities_by_depth[depth_opacity_idx]))
return std::clamp(layer_opacities_by_depth[depth_opacity_idx], 1e-4f, 0.9999f);
return component < layer_opacities.size() && std::isfinite(layer_opacities[component]) ?
std::clamp(layer_opacities[component], 1e-4f, 0.9999f) :
0.5f;
}
std::array<float, 3> mix_ordered_stack_beer_lambert_rgb(const std::vector<std::array<float, 3>> &colors_with_background,
const std::vector<uint16_t> &surface_to_deep,
const std::vector<float> &layer_opacities,
float surface_scatter)
float surface_scatter,
const std::vector<float> &layer_opacities_by_depth)
{
if (colors_with_background.empty() || surface_to_deep.empty())
return colors_with_background.empty() ? std::array<float, 3>{ { 0.f, 0.f, 0.f } } : colors_with_background.back();
@@ -567,13 +585,15 @@ std::array<float, 3> mix_ordered_stack_beer_lambert_rgb(const std::vector<std::a
bool surface_layer = true;
const float safe_surface_scatter =
std::clamp(std::isfinite(surface_scatter) ? surface_scatter : 0.f, 0.f, 0.5f);
for (uint16_t component_idx : surface_to_deep) {
for (size_t depth_idx = 0; depth_idx < surface_to_deep.size(); ++depth_idx) {
const uint16_t component_idx = surface_to_deep[depth_idx];
if (size_t(component_idx) >= component_count)
continue;
const float opacity =
size_t(component_idx) < layer_opacities.size() && std::isfinite(layer_opacities[size_t(component_idx)]) ?
std::clamp(layer_opacities[size_t(component_idx)], 1e-4f, 0.9999f) :
0.5f;
const float opacity = ordered_stack_layer_opacity(layer_opacities,
layer_opacities_by_depth,
component_count,
depth_idx,
component_idx);
std::array<float, 3> transmission =
beer_lambert_rgb_transmission(colors_with_background[size_t(component_idx)], 1.f - opacity);
if (surface_layer) {
@@ -606,7 +626,8 @@ std::array<float, 3> mix_ordered_stack_td_effective_alpha(
const std::vector<uint16_t> &surface_to_deep,
const std::vector<float> &layer_opacities,
float surface_scatter,
const std::vector<ColorSolverStackComponentRole> &component_roles)
const std::vector<ColorSolverStackComponentRole> &component_roles,
const std::vector<float> &layer_opacities_by_depth)
{
if (colors_with_background.empty() || surface_to_deep.empty())
return colors_with_background.empty() ? std::array<float, 3>{ { 0.f, 0.f, 0.f } } : colors_with_background.back();
@@ -617,13 +638,15 @@ std::array<float, 3> mix_ordered_stack_td_effective_alpha(
bool surface_layer = true;
const float safe_surface_scatter =
std::clamp(std::isfinite(surface_scatter) ? surface_scatter : 0.f, 0.f, 0.5f);
for (uint16_t component_idx : surface_to_deep) {
for (size_t depth_idx = 0; depth_idx < surface_to_deep.size(); ++depth_idx) {
const uint16_t component_idx = surface_to_deep[depth_idx];
if (size_t(component_idx) >= component_count)
continue;
const float opacity =
size_t(component_idx) < layer_opacities.size() && std::isfinite(layer_opacities[size_t(component_idx)]) ?
std::clamp(layer_opacities[size_t(component_idx)], 1e-4f, 0.9999f) :
0.5f;
const float opacity = ordered_stack_layer_opacity(layer_opacities,
layer_opacities_by_depth,
component_count,
depth_idx,
component_idx);
const float scalar_transmission = std::pow(1.f - opacity, TD_EFFECTIVE_ALPHA_DENSITY_SCALE);
const ColorSolverStackComponentRole role =
size_t(component_idx) < component_roles.size() ?
@@ -664,15 +687,16 @@ std::array<float, 3> mix_ordered_stack_with_buffers(const std::vector<std::array
float surface_scatter,
bool beer_lambert_rgb_correction,
bool td_effective_alpha_correction,
const std::vector<ColorSolverStackComponentRole> &component_roles)
const std::vector<ColorSolverStackComponentRole> &component_roles,
const std::vector<float> &layer_opacities_by_depth)
{
if (colors_with_background.empty() || surface_to_deep.empty())
return colors_with_background.empty() ? std::array<float, 3>{ { 0.f, 0.f, 0.f } } : colors_with_background.back();
if (td_effective_alpha_correction)
return mix_ordered_stack_td_effective_alpha(colors_with_background, surface_to_deep, layer_opacities, 0.f, component_roles);
return mix_ordered_stack_td_effective_alpha(colors_with_background, surface_to_deep, layer_opacities, 0.f, component_roles, layer_opacities_by_depth);
if (beer_lambert_rgb_correction)
return mix_ordered_stack_beer_lambert_rgb(colors_with_background, surface_to_deep, layer_opacities, surface_scatter);
return mix_ordered_stack_beer_lambert_rgb(colors_with_background, surface_to_deep, layer_opacities, surface_scatter, layer_opacities_by_depth);
const size_t component_count = colors_with_background.size() - 1;
weights.assign(colors_with_background.size(), 0.f);
@@ -680,13 +704,15 @@ std::array<float, 3> mix_ordered_stack_with_buffers(const std::vector<std::array
bool surface_layer = true;
const float safe_surface_scatter =
std::clamp(std::isfinite(surface_scatter) ? surface_scatter : 0.f, 0.f, 0.5f);
for (uint16_t component_idx : surface_to_deep) {
for (size_t depth_idx = 0; depth_idx < surface_to_deep.size(); ++depth_idx) {
const uint16_t component_idx = surface_to_deep[depth_idx];
if (size_t(component_idx) >= component_count)
continue;
float opacity =
size_t(component_idx) < layer_opacities.size() && std::isfinite(layer_opacities[size_t(component_idx)]) ?
std::clamp(layer_opacities[size_t(component_idx)], 1e-4f, 0.9999f) :
0.5f;
float opacity = ordered_stack_layer_opacity(layer_opacities,
layer_opacities_by_depth,
component_count,
depth_idx,
component_idx);
if (surface_layer) {
opacity = std::clamp(safe_surface_scatter + (1.f - safe_surface_scatter) * opacity, 1e-4f, 0.9999f);
surface_layer = false;
@@ -1014,7 +1040,8 @@ void append_ordered_stack_candidate(ColorSolverOrderedStackCandidateSet &c
float surface_scatter,
bool beer_lambert_rgb_correction,
bool td_effective_alpha_correction,
const std::vector<ColorSolverStackComponentRole> &component_roles)
const std::vector<ColorSolverStackComponentRole> &component_roles,
const std::vector<float> &layer_opacities_by_depth)
{
std::vector<uint16_t> simulated_surface_to_deep;
const std::vector<uint16_t> *mix_stack = &surface_to_deep;
@@ -1031,7 +1058,8 @@ void append_ordered_stack_candidate(ColorSolverOrderedStackCandidateSet &c
surface_scatter,
beer_lambert_rgb_correction,
td_effective_alpha_correction,
component_roles);
component_roles,
layer_opacities_by_depth);
const std::array<float, 3> perceptual = oklab_from_srgb(mixed);
candidates.rgbs.emplace_back(mixed[0]);
candidates.rgbs.emplace_back(mixed[1]);
@@ -1109,7 +1137,8 @@ std::array<float, 3> mix_color_solver_ordered_stack(const std::vector<std::array
float surface_scatter,
bool beer_lambert_rgb_correction,
bool td_effective_alpha_correction,
const std::vector<ColorSolverStackComponentRole> &component_roles)
const std::vector<ColorSolverStackComponentRole> &component_roles,
const std::vector<float> &layer_opacities_by_depth)
{
if (component_colors.empty() || surface_to_deep.empty())
return background_rgb;
@@ -1125,7 +1154,8 @@ std::array<float, 3> mix_color_solver_ordered_stack(const std::vector<std::array
surface_scatter,
beer_lambert_rgb_correction,
td_effective_alpha_correction,
component_roles);
component_roles,
layer_opacities_by_depth);
}
std::array<float, 3> color_solver_oklab_from_srgb(const std::array<float, 3> &rgb)
@@ -1263,7 +1293,8 @@ std::string color_solver_ordered_stack_candidate_cache_key(const std::vector<std
bool beer_lambert_rgb_correction,
bool td_effective_alpha_correction,
const std::vector<ColorSolverStackComponentRole> &component_roles,
bool beam_search_stack_expansion)
bool beam_search_stack_expansion,
const std::vector<float> &layer_opacities_by_depth)
{
std::ostringstream key;
key << component_colors.size();
@@ -1306,6 +1337,15 @@ std::string color_solver_ordered_stack_candidate_cache_key(const std::vector<std
0.5f;
key << ',' << int(std::lround(opacity * 1000000.f));
}
if (!layer_opacities_by_depth.empty()) {
key << "|opd";
for (const float opacity_value : layer_opacities_by_depth) {
const float opacity = std::isfinite(opacity_value) ?
std::clamp(opacity_value, 1e-4f, 0.9999f) :
0.5f;
key << ',' << int(std::lround(opacity * 1000000.f));
}
}
return key.str();
}
@@ -1322,7 +1362,8 @@ ColorSolverOrderedStackCandidateSet build_color_solver_ordered_stack_candidates(
bool beer_lambert_rgb_correction,
bool td_effective_alpha_correction,
const std::vector<ColorSolverStackComponentRole> &component_roles,
bool beam_search_stack_expansion)
bool beam_search_stack_expansion,
const std::vector<float> &layer_opacities_by_depth)
{
ColorSolverOrderedStackCandidateSet candidates;
int simulated_depth = simulated_stack_depth > 0 ? simulated_stack_depth : stack_depth;
@@ -1363,7 +1404,8 @@ ColorSolverOrderedStackCandidateSet build_color_solver_ordered_stack_candidates(
surface_scatter,
beer_lambert_rgb_correction,
td_effective_alpha_correction,
component_roles);
component_roles,
layer_opacities_by_depth);
return;
}
@@ -1416,7 +1458,8 @@ ColorSolverOrderedStackCandidateSet build_color_solver_ordered_stack_candidates(
surface_scatter,
beer_lambert_rgb_correction,
td_effective_alpha_correction,
component_roles);
component_roles,
layer_opacities_by_depth);
}
return;
}
@@ -1447,7 +1490,8 @@ const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates
bool beer_lambert_rgb_correction,
bool td_effective_alpha_correction,
const std::vector<ColorSolverStackComponentRole> &component_roles,
bool beam_search_stack_expansion)
bool beam_search_stack_expansion,
const std::vector<float> &layer_opacities_by_depth)
{
const std::string key =
color_solver_ordered_stack_candidate_cache_key(component_colors,
@@ -1462,7 +1506,8 @@ const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates
beer_lambert_rgb_correction,
td_effective_alpha_correction,
component_roles,
beam_search_stack_expansion);
beam_search_stack_expansion,
layer_opacities_by_depth);
auto it = cache.find(key);
if (it != cache.end())
return it->second;
@@ -1480,7 +1525,8 @@ const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates
beer_lambert_rgb_correction,
td_effective_alpha_correction,
component_roles,
beam_search_stack_expansion)).first->second;
beam_search_stack_expansion,
layer_opacities_by_depth)).first->second;
}
ColorSolverOrderedStackResult solve_color_solver_ordered_stack_result_for_target(

View File

@@ -131,7 +131,8 @@ std::array<float, 3> mix_color_solver_ordered_stack(const std::vector<std::array
float surface_scatter = 0.f,
bool beer_lambert_rgb_correction = false,
bool td_effective_alpha_correction = false,
const std::vector<ColorSolverStackComponentRole> &component_roles = {});
const std::vector<ColorSolverStackComponentRole> &component_roles = {},
const std::vector<float> &layer_opacities_by_depth = {});
std::array<float, 3> color_solver_oklab_from_srgb(const std::array<float, 3> &rgb);
std::array<float, 3> color_solver_srgb_from_oklab(const std::array<float, 3> &oklab);
@@ -161,7 +162,8 @@ std::string color_solver_ordered_stack_candidate_cache_key(const std::vector<std
bool beer_lambert_rgb_correction = false,
bool td_effective_alpha_correction = false,
const std::vector<ColorSolverStackComponentRole> &component_roles = {},
bool beam_search_stack_expansion = false);
bool beam_search_stack_expansion = false,
const std::vector<float> &layer_opacities_by_depth = {});
ColorSolverOrderedStackCandidateSet build_color_solver_ordered_stack_candidates(
const std::vector<std::array<float, 3>> &component_colors,
const std::vector<float> &layer_opacities,
@@ -175,7 +177,8 @@ ColorSolverOrderedStackCandidateSet build_color_solver_ordered_stack_candidates(
bool beer_lambert_rgb_correction = false,
bool td_effective_alpha_correction = false,
const std::vector<ColorSolverStackComponentRole> &component_roles = {},
bool beam_search_stack_expansion = false);
bool beam_search_stack_expansion = false,
const std::vector<float> &layer_opacities_by_depth = {});
const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates(
ColorSolverOrderedStackCandidateCache &cache,
const std::vector<std::array<float, 3>> &component_colors,
@@ -190,7 +193,8 @@ const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates
bool beer_lambert_rgb_correction = false,
bool td_effective_alpha_correction = false,
const std::vector<ColorSolverStackComponentRole> &component_roles = {},
bool beam_search_stack_expansion = false);
bool beam_search_stack_expansion = false,
const std::vector<float> &layer_opacities_by_depth = {});
ColorSolverOrderedStackResult solve_color_solver_ordered_stack_result_for_target(
const ColorSolverOrderedStackCandidateSet &candidates,
const std::array<float, 3> &target_rgb,

View File

@@ -518,6 +518,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_variable_layer_height_compensation_enabled = TextureMappingZone::DefaultTopSurfaceContoningVariableLayerHeightCompensationEnabled;
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;
@@ -1649,6 +1650,24 @@ static std::vector<ExPolygons> top_surface_image_contoning_stack_areas(const Lay
return out;
}
static std::vector<float> top_surface_image_contoning_surface_to_deep_layer_heights(
const Layer &source_layer,
int stack_layers,
TopSurfaceImageSourceSurface source_surface)
{
std::vector<float> out;
out.reserve(size_t(std::max(0, stack_layers)));
const Layer *stack_layer = &source_layer;
for (int depth = 0; depth < stack_layers && stack_layer != nullptr; ++depth) {
const float height = float(stack_layer->height);
out.emplace_back(std::isfinite(height) && height > 0.f ? height : 0.f);
stack_layer = source_surface == TopSurfaceImageSourceSurface::Top ?
stack_layer->lower_layer :
stack_layer->upper_layer;
}
return out;
}
static double top_surface_image_scaled_area_mm2(double scaled_area)
{
return std::abs(scaled_area) * SCALING_FACTOR * SCALING_FACTOR;
@@ -2219,6 +2238,7 @@ private:
struct TopSurfaceImageContoningSourceContext {
TextureMappingOffsetContext offset_context;
std::vector<ExPolygons> stack_areas;
std::vector<float> surface_to_deep_layer_heights_mm;
ExPolygons normal_filter_bypass_area;
float threshold_deg { 0.f };
int stack_layers { 0 };
@@ -2263,6 +2283,7 @@ struct TopSurfaceImageContoningStackPlanKey {
bool surface_scatter { false };
bool beer_lambert_rgb_correction { false };
bool td_effective_alpha_correction { false };
bool variable_layer_height_compensation { false };
bool beam_search_stack_expansion { false };
int mix_model { TextureMappingZone::DefaultGenericSolverMixModel };
@@ -2298,6 +2319,7 @@ struct TopSurfaceImageContoningStackPlanKey {
surface_scatter,
beer_lambert_rgb_correction,
td_effective_alpha_correction,
variable_layer_height_compensation,
beam_search_stack_expansion,
mix_model) <
std::tie(rhs.source_layer,
@@ -2330,6 +2352,7 @@ struct TopSurfaceImageContoningStackPlanKey {
rhs.surface_scatter,
rhs.beer_lambert_rgb_correction,
rhs.td_effective_alpha_correction,
rhs.variable_layer_height_compensation,
rhs.beam_search_stack_expansion,
rhs.mix_model);
}
@@ -4079,6 +4102,7 @@ static std::optional<TopSurfaceImageContoningSolvedLabel> top_surface_image_cont
const TextureMappingContoningSolver &solver,
bool lower_surface,
int visible_layers,
const std::vector<float> &surface_to_deep_layer_heights_mm,
std::vector<TopSurfaceImageContoningVectorLabel> &labels,
std::map<std::pair<std::vector<unsigned int>, int>, int> &label_by_stack)
{
@@ -4101,7 +4125,10 @@ static std::optional<TopSurfaceImageContoningSolvedLabel> top_surface_image_cont
if (stack.rgb)
stack_rgb = stack.rgb;
else
stack_rgb = solver.stack_rgb(stack.bottom_to_top, lower_surface, visible_layers);
stack_rgb = solver.stack_rgb(stack.bottom_to_top,
lower_surface,
visible_layers,
surface_to_deep_layer_heights_mm);
if (!stack_rgb)
return std::nullopt;
@@ -4127,11 +4154,22 @@ static std::optional<TopSurfaceImageContoningSolvedLabel> top_surface_image_cont
int visible_layers,
const TextureMappingContoningSolver &solver,
bool lower_surface,
const std::vector<float> &surface_to_deep_layer_heights_mm,
std::vector<TopSurfaceImageContoningVectorLabel> &labels,
std::map<std::pair<std::vector<unsigned int>, int>, int> &label_by_stack)
{
TextureMappingContoningStack stack = solver.solve(rgb, solve_layers, lower_surface, visible_layers);
return top_surface_image_contoning_label_for_stack(stack, solver, lower_surface, visible_layers, labels, label_by_stack);
TextureMappingContoningStack stack = solver.solve(rgb,
solve_layers,
lower_surface,
visible_layers,
surface_to_deep_layer_heights_mm);
return top_surface_image_contoning_label_for_stack(stack,
solver,
lower_surface,
visible_layers,
surface_to_deep_layer_heights_mm,
labels,
label_by_stack);
}
static void top_surface_image_contoning_resolve_merged_grid_regions(
@@ -4145,6 +4183,7 @@ static void top_surface_image_contoning_resolve_merged_grid_regions(
int stack_layers,
int pattern_filaments,
bool lower_surface,
const std::vector<float> &surface_to_deep_layer_heights_mm,
const ThrowIfCanceled *throw_if_canceled)
{
if (grid.empty() || labels.empty() || cols <= 0 || rows <= 0 ||
@@ -4243,6 +4282,7 @@ static void top_surface_image_contoning_resolve_merged_grid_regions(
visible_layers,
solver,
lower_surface,
surface_to_deep_layer_heights_mm,
resolved_labels,
label_by_stack);
if (solved)
@@ -4313,6 +4353,9 @@ static std::optional<TopSurfaceImageContoningSourceContext> top_surface_image_co
top_surface_image_contoning_pattern_filaments(out.stack_layers, plan.contoning_pattern_filaments);
out.stack_areas =
top_surface_image_contoning_stack_areas(source_layer, plan.zone_id, out.stack_layers, source_surface, throw_if_canceled);
if (plan.contoning_variable_layer_height_compensation_enabled)
out.surface_to_deep_layer_heights_mm =
top_surface_image_contoning_surface_to_deep_layer_heights(source_layer, out.stack_layers, source_surface);
if (stack_area_extensions != nullptr) {
const size_t count = std::min(out.stack_areas.size(), stack_area_extensions->size());
for (size_t idx = 0; idx < count; ++idx) {
@@ -4401,6 +4444,7 @@ static void top_surface_image_contoning_solve_anchored_region(
solver,
lower_surface,
available_depth,
source_context.surface_to_deep_layer_heights_mm,
labels,
label_by_stack);
if (!solved)
@@ -4448,7 +4492,11 @@ static void top_surface_image_contoning_solve_anchored_region(
cell_samples[grid_idx] = sample;
cell_available_depths[grid_idx] = sample->available_depth;
++debug_sampled_cell_count;
cell_stacks[grid_idx] = solver.solve(sample->rgb, sample->solve_layers, lower_surface, sample->available_depth);
cell_stacks[grid_idx] = solver.solve(sample->rgb,
sample->solve_layers,
lower_surface,
sample->available_depth,
source_context.surface_to_deep_layer_heights_mm);
if (debug_stride > 0 &&
row % debug_stride == 0 &&
col % debug_stride == 0) {
@@ -4550,6 +4598,7 @@ static void top_surface_image_contoning_solve_anchored_region(
source_context.stack_layers,
source_context.pattern_filaments,
source_surface == TopSurfaceImageSourceSurface::Bottom,
source_context.surface_to_deep_layer_heights_mm,
throw_if_canceled);
if (debug_enabled)
top_surface_image_debug_accumulate_timing_step(debug_timing.steps,
@@ -5049,6 +5098,7 @@ static TopSurfaceImageContoningStackPlanKey top_surface_image_contoning_anchored
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.variable_layer_height_compensation = plan.contoning_variable_layer_height_compensation_enabled;
key.beam_search_stack_expansion = plan.contoning_beam_search_stack_expansion_enabled;
key.mix_model = plan.contoning_generic_solver_mix_model;
return key;
@@ -5184,6 +5234,7 @@ static std::vector<TopSurfaceImageContoningVectorRegion> top_surface_image_conto
solver,
source_surface == TopSurfaceImageSourceSurface::Bottom &&
plan.contoning_td_adjustment_enabled,
source->surface_to_deep_layer_heights_mm,
labels,
label_by_stack);
if (!solved)
@@ -5310,6 +5361,7 @@ static std::vector<TopSurfaceImageContoningVectorRegion> top_surface_image_conto
source->stack_layers,
source->pattern_filaments,
source_surface == TopSurfaceImageSourceSurface::Bottom,
source->surface_to_deep_layer_heights_mm,
throw_if_canceled);
}
check_canceled(throw_if_canceled);
@@ -5396,6 +5448,7 @@ static std::shared_ptr<const TopSurfaceImageContoningStackPlan> top_surface_imag
solver,
source_surface == TopSurfaceImageSourceSurface::Bottom &&
plan.contoning_td_adjustment_enabled,
source_context->surface_to_deep_layer_heights_mm,
out->labels,
label_by_stack);
if (!solved)
@@ -5527,6 +5580,7 @@ static std::shared_ptr<const TopSurfaceImageContoningStackPlan> top_surface_imag
source_context->stack_layers,
source_context->pattern_filaments,
source_surface == TopSurfaceImageSourceSurface::Bottom,
source_context->surface_to_deep_layer_heights_mm,
throw_if_canceled);
}
for (size_t idx = 0; idx < out->cells.size(); ++idx)
@@ -5586,6 +5640,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.variable_layer_height_compensation = plan.contoning_variable_layer_height_compensation_enabled;
key.beam_search_stack_expansion = plan.contoning_beam_search_stack_expansion_enabled;
key.mix_model = plan.contoning_generic_solver_mix_model;
return key;
@@ -6284,6 +6339,8 @@ static std::vector<TopSurfaceImageRegionPlan> top_surface_image_region_plans(
plan.contoning_td_adjustment_enabled &&
!plan.contoning_td_effective_alpha_correction_enabled &&
zone->top_surface_contoning_beer_lambert_rgb_correction_enabled;
plan.contoning_variable_layer_height_compensation_enabled =
zone->top_surface_contoning_variable_layer_height_compensation_enabled;
plan.contoning_generic_solver_mix_model =
std::clamp(zone->generic_solver_mix_model,
int(TextureMappingZone::GenericSolverPigmentPainter),

View File

@@ -729,6 +729,28 @@ static int top_surface_contoning_flat_surface_infill_mode_from_name(const std::s
return int(TextureMappingZone::ContoningFlatSurfaceInfillDefault);
}
static std::string top_surface_contoning_color_prediction_mode_name(int mode)
{
if (mode == int(TextureMappingZone::ContoningColorPredictionTdEffectiveAlpha))
return "td_effective_alpha";
if (mode == int(TextureMappingZone::ContoningColorPredictionBeerLambertRgb))
return "rgb_beer_lambert";
return "default";
}
static int top_surface_contoning_color_prediction_mode_from_name(std::string name)
{
std::transform(name.begin(), name.end(), name.begin(), [](unsigned char c) {
const char lowered = char(std::tolower(c));
return lowered == '-' || lowered == ' ' ? '_' : lowered;
});
if (name == "td_effective_alpha" || name == "effective_alpha")
return int(TextureMappingZone::ContoningColorPredictionTdEffectiveAlpha);
if (name == "rgb_beer_lambert" || name == "beer_lambert_rgb" || name == "beer_lambert")
return int(TextureMappingZone::ContoningColorPredictionBeerLambertRgb);
return TextureMappingZone::DefaultTopSurfaceContoningColorPredictionMode;
}
static std::string top_visible_recolor_aggressiveness_name(int mode)
{
switch (clamp_int(mode,
@@ -1183,8 +1205,10 @@ bool TextureMappingZone::operator==(const TextureMappingZone &rhs) const
rhs.effective_top_surface_contoning_surface_anchored_stack_optimizations_enabled() &&
top_surface_contoning_td_adjustment_enabled == rhs.top_surface_contoning_td_adjustment_enabled &&
effective_top_surface_contoning_surface_scatter_enabled() == rhs.effective_top_surface_contoning_surface_scatter_enabled() &&
top_surface_contoning_color_prediction_mode == rhs.top_surface_contoning_color_prediction_mode &&
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 &&
top_surface_contoning_variable_layer_height_compensation_enabled == rhs.top_surface_contoning_variable_layer_height_compensation_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 &&
@@ -1596,10 +1620,14 @@ std::string TextureMappingManager::serialize_entries()
zone.top_surface_contoning_td_adjustment_enabled;
texture["top_surface_contoning_surface_scatter_enabled"] =
zone.effective_top_surface_contoning_surface_scatter_enabled();
texture["top_surface_contoning_color_prediction_mode"] =
top_surface_contoning_color_prediction_mode_name(zone.top_surface_contoning_color_prediction_mode);
texture["top_surface_contoning_beer_lambert_rgb_correction_enabled"] =
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_variable_layer_height_compensation_enabled"] =
zone.top_surface_contoning_variable_layer_height_compensation_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;
@@ -1913,12 +1941,22 @@ void TextureMappingManager::load_entries(const std::string &serialized,
zone.top_surface_contoning_surface_scatter_enabled =
texture.value("top_surface_contoning_surface_scatter_enabled",
TextureMappingZone::DefaultTopSurfaceContoningSurfaceScatterEnabled);
auto color_prediction_mode_it = texture.find("top_surface_contoning_color_prediction_mode");
zone.top_surface_contoning_color_prediction_mode =
color_prediction_mode_it != texture.end() && color_prediction_mode_it->is_string() ?
top_surface_contoning_color_prediction_mode_from_name(color_prediction_mode_it->get<std::string>()) :
clamp_int(color_prediction_mode_it != texture.end() && color_prediction_mode_it->is_number_integer() ?
color_prediction_mode_it->get<int>() :
TextureMappingZone::DefaultTopSurfaceContoningColorPredictionMode,
int(TextureMappingZone::ContoningColorPredictionDefault),
int(TextureMappingZone::ContoningColorPredictionBeerLambertRgb));
zone.top_surface_contoning_beer_lambert_rgb_correction_enabled =
texture.value("top_surface_contoning_beer_lambert_rgb_correction_enabled",
TextureMappingZone::DefaultTopSurfaceContoningBeerLambertRgbCorrectionEnabled);
TextureMappingZone::DefaultTopSurfaceContoningBeerLambertRgbCorrectionEnabled;
zone.top_surface_contoning_td_effective_alpha_correction_enabled =
texture.value("top_surface_contoning_td_effective_alpha_correction_enabled",
TextureMappingZone::DefaultTopSurfaceContoningTdEffectiveAlphaCorrectionEnabled);
TextureMappingZone::DefaultTopSurfaceContoningTdEffectiveAlphaCorrectionEnabled;
zone.top_surface_contoning_variable_layer_height_compensation_enabled =
texture.value("top_surface_contoning_variable_layer_height_compensation_enabled",
TextureMappingZone::DefaultTopSurfaceContoningVariableLayerHeightCompensationEnabled);
zone.top_surface_contoning_beam_search_stack_expansion_enabled =
texture.value("top_surface_contoning_beam_search_stack_expansion_enabled",
TextureMappingZone::DefaultTopSurfaceContoningBeamSearchStackExpansionEnabled);

View File

@@ -89,6 +89,12 @@ struct TextureMappingZone
ContoningFlatSurfaceInfillRectilinearWithBoundary = 7
};
enum TopSurfaceContoningColorPredictionMode : uint8_t {
ContoningColorPredictionDefault = 0,
ContoningColorPredictionTdEffectiveAlpha = 1,
ContoningColorPredictionBeerLambertRgb = 2
};
enum FilamentColorMode : uint8_t {
FilamentColorAny = 0,
FilamentColorRGB = 1,
@@ -207,8 +213,13 @@ struct TextureMappingZone
static constexpr bool DefaultTopSurfaceContoningSurfaceAnchoredStackOptimizationsEnabled = true;
static constexpr bool DefaultTopSurfaceContoningTdAdjustmentEnabled = true;
static constexpr bool DefaultTopSurfaceContoningSurfaceScatterEnabled = false;
static constexpr bool DefaultTopSurfaceContoningBeerLambertRgbCorrectionEnabled = false;
static constexpr bool DefaultTopSurfaceContoningTdEffectiveAlphaCorrectionEnabled = true;
static constexpr int DefaultTopSurfaceContoningColorPredictionMode = int(ContoningColorPredictionDefault);
static constexpr int SlicerDefaultTopSurfaceContoningColorPredictionMode = int(ContoningColorPredictionTdEffectiveAlpha);
static constexpr bool DefaultTopSurfaceContoningVariableLayerHeightCompensationEnabled = true;
static constexpr bool DefaultTopSurfaceContoningBeerLambertRgbCorrectionEnabled =
SlicerDefaultTopSurfaceContoningColorPredictionMode == int(ContoningColorPredictionBeerLambertRgb);
static constexpr bool DefaultTopSurfaceContoningTdEffectiveAlphaCorrectionEnabled =
SlicerDefaultTopSurfaceContoningColorPredictionMode == int(ContoningColorPredictionTdEffectiveAlpha);
static constexpr bool DefaultTopSurfaceContoningBeamSearchStackExpansionEnabled = true;
static constexpr bool DefaultCompactOffsetMode = true;
static constexpr bool DefaultUseLegacyFixedColorMode = false;
@@ -329,6 +340,15 @@ struct TextureMappingZone
return td_adjustment && surface_scatter && !td_effective_alpha;
}
static int effective_top_surface_contoning_color_prediction_mode(int mode)
{
if (mode == int(ContoningColorPredictionDefault))
return SlicerDefaultTopSurfaceContoningColorPredictionMode;
return std::clamp(mode,
int(ContoningColorPredictionTdEffectiveAlpha),
int(ContoningColorPredictionBeerLambertRgb));
}
static bool effective_top_surface_contoning_layer_phase_enabled(bool value, bool surface_anchored_stacks)
{
return effective_top_surface_contoning_layer_phase_enabled(value) &&
@@ -343,7 +363,7 @@ struct TextureMappingZone
static constexpr int normalize_top_surface_contoning_polygonize_resolution(int value)
{
return value <= 1 ? 1 : (value >= 8 ? 8 : (value >= 4 ? 4 : 2));
return value <= 1 ? 1 : (value >= 8 ? 8 : (value >= 4 ? 4 : (value >= 3 ? 3 : 2)));
}
struct LinearGradientAnchor {
@@ -431,6 +451,8 @@ struct TextureMappingZone
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;
int top_surface_contoning_color_prediction_mode = DefaultTopSurfaceContoningColorPredictionMode;
bool top_surface_contoning_variable_layer_height_compensation_enabled = DefaultTopSurfaceContoningVariableLayerHeightCompensationEnabled;
bool top_surface_contoning_beam_search_stack_expansion_enabled = DefaultTopSurfaceContoningBeamSearchStackExpansionEnabled;
bool compact_offset_mode = DefaultCompactOffsetMode;
bool use_legacy_fixed_color_mode = DefaultUseLegacyFixedColorMode;
@@ -589,6 +611,20 @@ struct TextureMappingZone
top_surface_contoning_td_effective_alpha_correction_enabled);
}
int effective_top_surface_contoning_color_prediction_mode() const
{
return TextureMappingZone::effective_top_surface_contoning_color_prediction_mode(
top_surface_contoning_color_prediction_mode);
}
void normalize_top_surface_contoning_td_correction()
{
const bool beer_lambert_rgb =
effective_top_surface_contoning_color_prediction_mode() == int(ContoningColorPredictionBeerLambertRgb);
top_surface_contoning_beer_lambert_rgb_correction_enabled = beer_lambert_rgb;
top_surface_contoning_td_effective_alpha_correction_enabled = !beer_lambert_rgb;
}
void apply_top_surface_contoning_experimental_defaults()
{
if (top_surface_image_printing_enabled &&
@@ -617,6 +653,8 @@ struct TextureMappingZone
top_surface_contoning_layer_phase_enabled = false;
top_surface_contoning_blue_noise_error_diffusion_enabled = false;
}
top_surface_contoning_td_adjustment_enabled = true;
normalize_top_surface_contoning_td_correction();
if (top_surface_contoning_td_effective_alpha_correction_enabled)
top_surface_contoning_surface_scatter_enabled = false;
}
@@ -687,6 +725,8 @@ struct TextureMappingZone
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_color_prediction_mode = DefaultTopSurfaceContoningColorPredictionMode;
top_surface_contoning_variable_layer_height_compensation_enabled = DefaultTopSurfaceContoningVariableLayerHeightCompensationEnabled;
top_surface_contoning_beam_search_stack_expansion_enabled = DefaultTopSurfaceContoningBeamSearchStackExpansionEnabled;
compact_offset_mode = DefaultCompactOffsetMode;
use_legacy_fixed_color_mode = DefaultUseLegacyFixedColorMode;

View File

@@ -413,6 +413,8 @@ TextureMappingContoningSolver::TextureMappingContoningSolver(const TextureMappin
m_td_adjustment_enabled &&
!m_td_effective_alpha_correction_enabled &&
zone.top_surface_contoning_beer_lambert_rgb_correction_enabled;
m_variable_layer_height_compensation_enabled =
m_td_adjustment_enabled && zone.top_surface_contoning_variable_layer_height_compensation_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)
@@ -490,7 +492,8 @@ std::optional<size_t> TextureMappingContoningSolver::component_index(unsigned in
std::optional<std::array<float, 3>> TextureMappingContoningSolver::stack_rgb(
const std::vector<unsigned int> &bottom_to_top,
bool lower_surface,
int visible_stack_layers) const
int visible_stack_layers,
const std::vector<float> &surface_to_deep_layer_heights_mm) const
{
if (bottom_to_top.empty() || !valid())
return std::nullopt;
@@ -542,6 +545,8 @@ std::optional<std::array<float, 3>> TextureMappingContoningSolver::stack_rgb(
surface_to_deep = std::move(repeated);
}
const std::vector<float> depth_layer_opacities =
layer_opacities_by_depth(surface_to_deep_layer_heights_mm, visible_depth);
return mix_color_solver_ordered_stack(m_component_colors,
surface_to_deep,
m_component_layer_opacity,
@@ -550,7 +555,34 @@ std::optional<std::array<float, 3>> TextureMappingContoningSolver::stack_rgb(
m_surface_scatter,
m_beer_lambert_rgb_correction_enabled,
m_td_effective_alpha_correction_enabled,
m_component_roles);
m_component_roles,
depth_layer_opacities);
}
std::vector<float> TextureMappingContoningSolver::layer_opacities_by_depth(
const std::vector<float> &surface_to_deep_layer_heights_mm,
int visible_depth) const
{
if (!m_variable_layer_height_compensation_enabled ||
surface_to_deep_layer_heights_mm.empty() ||
visible_depth <= 0 ||
m_effective_transmission_distances_mm.empty())
return {};
const int depth = std::min(visible_depth, TextureMappingZone::MaxTopSurfaceContoningStackLayers);
std::vector<float> out;
out.reserve(size_t(depth) * m_effective_transmission_distances_mm.size());
for (int depth_idx = 0; depth_idx < depth; ++depth_idx) {
float layer_height_mm =
depth_idx < int(surface_to_deep_layer_heights_mm.size()) ?
surface_to_deep_layer_heights_mm[size_t(depth_idx)] :
m_layer_height_mm;
if (!std::isfinite(layer_height_mm) || layer_height_mm <= 0.f)
layer_height_mm = m_layer_height_mm;
for (float td_mm : m_effective_transmission_distances_mm)
out.emplace_back(layer_opacity_from_td(td_mm > 0.f ? td_mm : 3.f, layer_height_mm));
}
return out;
}
void TextureMappingContoningSolver::arrange_stack_for_light_path(std::vector<unsigned int> &bottom_to_top,
@@ -621,7 +653,8 @@ void TextureMappingContoningSolver::arrange_stack_for_light_path(std::vector<uns
TextureMappingContoningStack TextureMappingContoningSolver::solve(const std::array<float, 3> &target_rgb,
int stack_layers,
bool lower_surface,
int visible_stack_layers) const
int visible_stack_layers,
const std::vector<float> &surface_to_deep_layer_heights_mm) const
{
TextureMappingContoningStack out;
if (!valid())
@@ -637,6 +670,8 @@ TextureMappingContoningStack TextureMappingContoningSolver::solve(const std::arr
requested_depth;
const int depth = std::min(requested_depth, visible_depth);
if (m_td_adjustment_enabled) {
const std::vector<float> depth_layer_opacities =
layer_opacities_by_depth(surface_to_deep_layer_heights_mm, visible_depth);
const ColorSolverOrderedStackCandidateSet *ordered_candidates = nullptr;
{
std::lock_guard<std::mutex> lock(*m_ordered_candidate_cache_mutex);
@@ -654,7 +689,8 @@ TextureMappingContoningStack TextureMappingContoningSolver::solve(const std::arr
m_beer_lambert_rgb_correction_enabled,
m_td_effective_alpha_correction_enabled,
m_component_roles,
m_beam_search_stack_expansion_enabled);
m_beam_search_stack_expansion_enabled,
depth_layer_opacities);
}
const ColorSolverOrderedStackResult solved =
solve_color_solver_ordered_stack_result_for_target(*ordered_candidates, target_rgb, ColorSolverMode::OklabSoftCap4Dark4);

View File

@@ -39,11 +39,13 @@ public:
TextureMappingContoningStack solve(const std::array<float, 3> &target_rgb,
int stack_layers,
bool lower_surface = false,
int visible_stack_layers = 0) const;
int visible_stack_layers = 0,
const std::vector<float> &surface_to_deep_layer_heights_mm = {}) const;
unsigned int component_for_depth(const std::array<float, 3> &target_rgb, int stack_layers, int depth_from_top, bool lower_surface = false) const;
std::optional<std::array<float, 3>> stack_rgb(const std::vector<unsigned int> &bottom_to_top,
bool lower_surface = false,
int visible_stack_layers = 0) const;
int visible_stack_layers = 0,
const std::vector<float> &surface_to_deep_layer_heights_mm = {}) const;
private:
struct Candidate {
@@ -57,6 +59,8 @@ private:
void arrange_stack_for_light_path(std::vector<unsigned int> &bottom_to_top,
const std::array<float, 3> &target_rgb) const;
std::optional<size_t> component_index(unsigned int component_id) const;
std::vector<float> layer_opacities_by_depth(const std::vector<float> &surface_to_deep_layer_heights_mm,
int visible_depth) const;
std::vector<unsigned int> m_component_ids;
std::vector<unsigned int> m_components_bottom_to_top;
@@ -71,6 +75,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_variable_layer_height_compensation_enabled { false };
bool m_beam_search_stack_expansion_enabled { false };
std::vector<ColorSolverStackComponentRole> m_component_roles;
mutable std::map<int, std::vector<Candidate>> m_candidates_by_depth;

View File

@@ -2094,6 +2094,50 @@ static int texture_mapping_generic_solver_mode_from_choice_selection(int selecti
}
}
static wxString texture_mapping_contoning_color_prediction_mode_label(int mode)
{
switch (TextureMappingZone::effective_top_surface_contoning_color_prediction_mode(mode)) {
case int(TextureMappingZone::ContoningColorPredictionBeerLambertRgb):
return _L("RGB Beer-Lambert - not recommended");
default:
return _L("TD Effective Alpha");
}
}
static wxString texture_mapping_contoning_color_prediction_default_label()
{
wxString label = _L("Default");
label += " (";
label += texture_mapping_contoning_color_prediction_mode_label(
TextureMappingZone::SlicerDefaultTopSurfaceContoningColorPredictionMode);
label += ")";
return label;
}
static int texture_mapping_contoning_color_prediction_mode_choice_selection(int mode)
{
if (mode == int(TextureMappingZone::ContoningColorPredictionDefault))
return 0;
switch (TextureMappingZone::effective_top_surface_contoning_color_prediction_mode(mode)) {
case int(TextureMappingZone::ContoningColorPredictionBeerLambertRgb):
return 2;
default:
return 1;
}
}
static int texture_mapping_contoning_color_prediction_mode_from_choice_selection(int selection)
{
switch (selection) {
case 1:
return int(TextureMappingZone::ContoningColorPredictionTdEffectiveAlpha);
case 2:
return int(TextureMappingZone::ContoningColorPredictionBeerLambertRgb);
default:
return TextureMappingZone::DefaultTopSurfaceContoningColorPredictionMode;
}
}
class TextureMappingAdvancedOptionsDialog : public wxDialog
{
public:
@@ -2159,8 +2203,10 @@ public:
bool top_surface_contoning_beam_search_stack_expansion_enabled,
bool top_surface_contoning_td_adjustment_enabled,
bool top_surface_contoning_surface_scatter_enabled,
int top_surface_contoning_color_prediction_mode,
bool top_surface_contoning_beer_lambert_rgb_correction_enabled,
bool top_surface_contoning_td_effective_alpha_correction_enabled,
bool top_surface_contoning_variable_layer_height_compensation_enabled,
const TextureMappingZoneShellUsageSummary &top_surface_contoning_shell_usage,
const TextureMappingManager &texture_mapping_zones,
const TextureMappingGlobalSettings &global_settings,
@@ -2175,6 +2221,9 @@ public:
{
(void) reduce_outer_surface_texture;
(void) top_surface_contoning_min_feature_mm;
(void) top_surface_contoning_td_adjustment_enabled;
(void) top_surface_contoning_beer_lambert_rgb_correction_enabled;
(void) top_surface_contoning_td_effective_alpha_correction_enabled;
m_modulation_mode_manually_changed = modulation_mode_manually_changed;
m_strength_offsets_expanded = initial_strength_offsets_expanded;
m_top_surface_contoning_shell_usage = top_surface_contoning_shell_usage;
@@ -2841,43 +2890,43 @@ public:
0,
wxEXPAND | wxTOP | wxBOTTOM,
gap / 2);
m_top_surface_contoning_td_adjustment_checkbox =
new wxCheckBox(m_top_surface_contoning_checkboxes_panel, wxID_ANY, _L("TD adjustment"));
m_top_surface_contoning_td_adjustment_checkbox->SetValue(top_surface_contoning_td_adjustment_enabled);
m_top_surface_contoning_td_adjustment_checkbox->SetMinSize(
wxSize(-1, std::max(m_top_surface_contoning_td_adjustment_checkbox->GetBestSize().GetHeight(), FromDIP(24))));
contoning_checkboxes_root->Add(m_top_surface_contoning_td_adjustment_checkbox,
0,
wxEXPAND | wxTOP | wxBOTTOM,
gap / 2);
const bool top_surface_contoning_td_effective_alpha_correction_selected =
TextureMappingZone::effective_top_surface_contoning_color_prediction_mode(top_surface_contoning_color_prediction_mode) ==
int(TextureMappingZone::ContoningColorPredictionTdEffectiveAlpha);
m_top_surface_contoning_surface_scatter_checkbox =
new wxCheckBox(m_top_surface_contoning_checkboxes_panel, wxID_ANY, _L("Surface scatter correction"));
m_top_surface_contoning_surface_scatter_checkbox->SetValue(
TextureMappingZone::effective_top_surface_contoning_surface_scatter_enabled(
top_surface_contoning_td_adjustment_enabled,
true,
top_surface_contoning_surface_scatter_enabled,
top_surface_contoning_td_effective_alpha_correction_enabled));
top_surface_contoning_td_effective_alpha_correction_selected));
m_top_surface_contoning_surface_scatter_checkbox->SetMinSize(
wxSize(-1, std::max(m_top_surface_contoning_surface_scatter_checkbox->GetBestSize().GetHeight(), FromDIP(24))));
contoning_checkboxes_root->Add(m_top_surface_contoning_surface_scatter_checkbox,
0,
wxEXPAND | wxTOP | wxBOTTOM,
gap / 2);
m_top_surface_contoning_td_effective_alpha_correction_checkbox =
new wxCheckBox(m_top_surface_contoning_checkboxes_panel, wxID_ANY, _L("TD Effective Alpha correction"));
m_top_surface_contoning_td_effective_alpha_correction_checkbox->SetValue(top_surface_contoning_td_effective_alpha_correction_enabled);
m_top_surface_contoning_td_effective_alpha_correction_checkbox->SetMinSize(
wxSize(-1, std::max(m_top_surface_contoning_td_effective_alpha_correction_checkbox->GetBestSize().GetHeight(), FromDIP(24))));
contoning_checkboxes_root->Add(m_top_surface_contoning_td_effective_alpha_correction_checkbox,
0,
wxEXPAND | wxTOP | wxBOTTOM,
gap / 2);
m_top_surface_contoning_beer_lambert_rgb_correction_checkbox =
new wxCheckBox(m_top_surface_contoning_checkboxes_panel, wxID_ANY, _L("RGB Beer-Lambert correction"));
m_top_surface_contoning_beer_lambert_rgb_correction_checkbox->SetValue(top_surface_contoning_beer_lambert_rgb_correction_enabled);
m_top_surface_contoning_beer_lambert_rgb_correction_checkbox->SetMinSize(
wxSize(-1, std::max(m_top_surface_contoning_beer_lambert_rgb_correction_checkbox->GetBestSize().GetHeight(), FromDIP(24))));
contoning_checkboxes_root->Add(m_top_surface_contoning_beer_lambert_rgb_correction_checkbox,
auto *contoning_td_correction_row = new wxBoxSizer(wxHORIZONTAL);
contoning_td_correction_row->Add(new wxStaticText(m_top_surface_contoning_checkboxes_panel, wxID_ANY, _L("Color prediction mode")),
0,
wxALIGN_CENTER_VERTICAL | wxRIGHT,
gap);
wxArrayString contoning_td_correction_choices;
contoning_td_correction_choices.Add(texture_mapping_contoning_color_prediction_default_label());
contoning_td_correction_choices.Add(texture_mapping_contoning_color_prediction_mode_label(int(TextureMappingZone::ContoningColorPredictionTdEffectiveAlpha)));
contoning_td_correction_choices.Add(texture_mapping_contoning_color_prediction_mode_label(int(TextureMappingZone::ContoningColorPredictionBeerLambertRgb)));
m_top_surface_contoning_td_correction_choice =
new wxChoice(m_top_surface_contoning_checkboxes_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, contoning_td_correction_choices);
m_top_surface_contoning_td_correction_choice->SetSelection(
texture_mapping_contoning_color_prediction_mode_choice_selection(top_surface_contoning_color_prediction_mode));
contoning_td_correction_row->Add(m_top_surface_contoning_td_correction_choice, 1, wxALIGN_CENTER_VERTICAL);
contoning_checkboxes_root->Add(contoning_td_correction_row, 0, wxEXPAND | wxTOP | wxBOTTOM, gap / 2);
m_top_surface_contoning_variable_layer_height_compensation_checkbox =
new wxCheckBox(m_top_surface_contoning_checkboxes_panel, wxID_ANY, _L("Variable layer height compensation"));
m_top_surface_contoning_variable_layer_height_compensation_checkbox->SetValue(top_surface_contoning_variable_layer_height_compensation_enabled);
m_top_surface_contoning_variable_layer_height_compensation_checkbox->SetMinSize(
wxSize(-1, std::max(m_top_surface_contoning_variable_layer_height_compensation_checkbox->GetBestSize().GetHeight(), FromDIP(24))));
contoning_checkboxes_root->Add(m_top_surface_contoning_variable_layer_height_compensation_checkbox,
0,
wxEXPAND | wxTOP | wxBOTTOM,
gap / 2);
@@ -2992,15 +3041,6 @@ public:
0,
wxEXPAND | wxTOP | wxBOTTOM,
gap / 2);
m_top_surface_contoning_fast_mode_checkbox =
new wxCheckBox(m_top_surface_contoning_checkboxes_panel, wxID_ANY, _L("Fast mode"));
m_top_surface_contoning_fast_mode_checkbox->SetValue(top_surface_contoning_fast_mode_enabled);
m_top_surface_contoning_fast_mode_checkbox->SetMinSize(
wxSize(-1, std::max(m_top_surface_contoning_fast_mode_checkbox->GetBestSize().GetHeight(), FromDIP(24))));
contoning_checkboxes_root->Add(m_top_surface_contoning_fast_mode_checkbox,
0,
wxEXPAND | wxTOP | wxBOTTOM,
gap / 2);
m_top_surface_contoning_polygonize_resolution_panel = new wxPanel(m_top_surface_contoning_checkboxes_panel, wxID_ANY);
auto *contoning_polygonize_resolution_row = new wxBoxSizer(wxHORIZONTAL);
m_top_surface_contoning_polygonize_resolution_panel->SetSizer(contoning_polygonize_resolution_row);
@@ -3011,6 +3051,7 @@ public:
wxArrayString contoning_polygonize_resolution_choices;
contoning_polygonize_resolution_choices.Add(_L("1x"));
contoning_polygonize_resolution_choices.Add(_L("2x"));
contoning_polygonize_resolution_choices.Add(_L("3x"));
contoning_polygonize_resolution_choices.Add(_L("4x"));
contoning_polygonize_resolution_choices.Add(_L("8x (slow)"));
m_top_surface_contoning_polygonize_resolution_choice =
@@ -3018,12 +3059,21 @@ public:
const int polygonize_resolution = TextureMappingZone::normalize_top_surface_contoning_polygonize_resolution(top_surface_contoning_polygonize_resolution);
m_top_surface_contoning_polygonize_resolution_choice->SetSelection(
polygonize_resolution == 1 ? 0 :
(polygonize_resolution == 2 ? 1 : (polygonize_resolution == 4 ? 2 : 3)));
(polygonize_resolution == 2 ? 1 : (polygonize_resolution == 3 ? 2 : (polygonize_resolution == 4 ? 3 : 4))));
contoning_polygonize_resolution_row->Add(m_top_surface_contoning_polygonize_resolution_choice, 1, wxEXPAND);
contoning_checkboxes_root->Add(m_top_surface_contoning_polygonize_resolution_panel,
0,
wxEXPAND | wxTOP | wxBOTTOM,
gap / 2);
m_top_surface_contoning_fast_mode_checkbox =
new wxCheckBox(m_top_surface_contoning_checkboxes_panel, wxID_ANY, _L("Fast mode"));
m_top_surface_contoning_fast_mode_checkbox->SetValue(top_surface_contoning_fast_mode_enabled);
m_top_surface_contoning_fast_mode_checkbox->SetMinSize(
wxSize(-1, std::max(m_top_surface_contoning_fast_mode_checkbox->GetBestSize().GetHeight(), FromDIP(24))));
contoning_checkboxes_root->Add(m_top_surface_contoning_fast_mode_checkbox,
0,
wxEXPAND | wxTOP | wxBOTTOM,
gap / 2);
if (TextureMappingZone::ShowExperimentalTopSurfaceContoningOptions) {
m_top_surface_contoning_surface_anchored_stacks_checkbox =
new wxCheckBox(m_top_surface_contoning_checkboxes_panel, wxID_ANY, _L("Surface-anchored stacks"));
@@ -3085,25 +3135,19 @@ public:
update_top_surface_image_options_visibility(true);
});
}
if (m_top_surface_contoning_td_adjustment_checkbox != nullptr) {
m_top_surface_contoning_td_adjustment_checkbox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &) {
update_top_surface_image_options_visibility(false);
queue_top_surface_contoning_message_update(true);
});
}
if (m_top_surface_contoning_surface_scatter_checkbox != nullptr) {
m_top_surface_contoning_surface_scatter_checkbox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &) {
queue_top_surface_contoning_message_update(true);
});
}
if (m_top_surface_contoning_td_effective_alpha_correction_checkbox != nullptr) {
m_top_surface_contoning_td_effective_alpha_correction_checkbox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &) {
if (m_top_surface_contoning_td_correction_choice != nullptr) {
m_top_surface_contoning_td_correction_choice->Bind(wxEVT_CHOICE, [this](wxCommandEvent &) {
update_top_surface_image_options_visibility(false);
queue_top_surface_contoning_message_update(true);
});
}
if (m_top_surface_contoning_beer_lambert_rgb_correction_checkbox != nullptr) {
m_top_surface_contoning_beer_lambert_rgb_correction_checkbox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &) {
if (m_top_surface_contoning_variable_layer_height_compensation_checkbox != nullptr) {
m_top_surface_contoning_variable_layer_height_compensation_checkbox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &) {
queue_top_surface_contoning_message_update(true);
});
}
@@ -3595,8 +3639,9 @@ public:
switch (selection) {
case 0: return 1;
case 1: return 2;
case 2: return 4;
case 3: return 8;
case 2: return 3;
case 3: return 4;
case 4: return 8;
default: return TextureMappingZone::DefaultTopSurfaceContoningPolygonizeResolution;
}
}
@@ -3626,9 +3671,20 @@ public:
}
bool top_surface_contoning_td_adjustment_enabled() const
{
return m_top_surface_contoning_td_adjustment_checkbox == nullptr ?
TextureMappingZone::DefaultTopSurfaceContoningTdAdjustmentEnabled :
m_top_surface_contoning_td_adjustment_checkbox->GetValue();
return true;
}
int top_surface_contoning_color_prediction_mode() const
{
return m_top_surface_contoning_td_correction_choice == nullptr ?
TextureMappingZone::DefaultTopSurfaceContoningColorPredictionMode :
texture_mapping_contoning_color_prediction_mode_from_choice_selection(
m_top_surface_contoning_td_correction_choice->GetSelection());
}
bool top_surface_contoning_td_effective_alpha_correction_selected() const
{
return TextureMappingZone::effective_top_surface_contoning_color_prediction_mode(
top_surface_contoning_color_prediction_mode()) ==
int(TextureMappingZone::ContoningColorPredictionTdEffectiveAlpha);
}
bool top_surface_contoning_surface_scatter_enabled() const
{
@@ -3642,17 +3698,20 @@ public:
bool top_surface_contoning_beer_lambert_rgb_correction_enabled() const
{
return top_surface_contoning_td_adjustment_enabled() &&
!top_surface_contoning_td_effective_alpha_correction_enabled() &&
(m_top_surface_contoning_beer_lambert_rgb_correction_checkbox == nullptr ?
TextureMappingZone::DefaultTopSurfaceContoningBeerLambertRgbCorrectionEnabled :
m_top_surface_contoning_beer_lambert_rgb_correction_checkbox->GetValue());
TextureMappingZone::effective_top_surface_contoning_color_prediction_mode(
top_surface_contoning_color_prediction_mode()) ==
int(TextureMappingZone::ContoningColorPredictionBeerLambertRgb);
}
bool top_surface_contoning_td_effective_alpha_correction_enabled() const
{
return top_surface_contoning_td_adjustment_enabled() &&
(m_top_surface_contoning_td_effective_alpha_correction_checkbox == nullptr ?
TextureMappingZone::DefaultTopSurfaceContoningTdEffectiveAlphaCorrectionEnabled :
m_top_surface_contoning_td_effective_alpha_correction_checkbox->GetValue());
top_surface_contoning_td_effective_alpha_correction_selected();
}
bool top_surface_contoning_variable_layer_height_compensation_enabled() const
{
return m_top_surface_contoning_variable_layer_height_compensation_checkbox == nullptr ?
TextureMappingZone::DefaultTopSurfaceContoningVariableLayerHeightCompensationEnabled :
m_top_surface_contoning_variable_layer_height_compensation_checkbox->GetValue();
}
bool minimum_visibility_offset_enabled() const
{
@@ -4438,43 +4497,23 @@ private:
m_top_surface_contoning_color_lower_surfaces_checkbox->Show(contoning);
m_top_surface_contoning_color_lower_surfaces_checkbox->Enable(contoning);
}
if (m_top_surface_contoning_td_adjustment_checkbox != nullptr) {
m_top_surface_contoning_td_adjustment_checkbox->Show(contoning);
m_top_surface_contoning_td_adjustment_checkbox->Enable(contoning);
}
if (m_top_surface_contoning_surface_scatter_checkbox != nullptr) {
const bool td_adjustment =
contoning &&
m_top_surface_contoning_td_adjustment_checkbox != nullptr &&
m_top_surface_contoning_td_adjustment_checkbox->GetValue();
const bool td_adjustment = contoning;
const bool td_effective_alpha =
td_adjustment &&
m_top_surface_contoning_td_effective_alpha_correction_checkbox != nullptr &&
m_top_surface_contoning_td_effective_alpha_correction_checkbox->GetValue();
top_surface_contoning_td_effective_alpha_correction_selected();
m_top_surface_contoning_surface_scatter_checkbox->Show(contoning);
m_top_surface_contoning_surface_scatter_checkbox->Enable(td_adjustment && !td_effective_alpha);
if (td_effective_alpha && m_top_surface_contoning_surface_scatter_checkbox->GetValue())
m_top_surface_contoning_surface_scatter_checkbox->SetValue(false);
}
if (m_top_surface_contoning_beer_lambert_rgb_correction_checkbox != nullptr) {
const bool td_adjustment =
contoning &&
m_top_surface_contoning_td_adjustment_checkbox != nullptr &&
m_top_surface_contoning_td_adjustment_checkbox->GetValue();
const bool td_effective_alpha =
td_adjustment &&
m_top_surface_contoning_td_effective_alpha_correction_checkbox != nullptr &&
m_top_surface_contoning_td_effective_alpha_correction_checkbox->GetValue();
m_top_surface_contoning_beer_lambert_rgb_correction_checkbox->Show(contoning);
m_top_surface_contoning_beer_lambert_rgb_correction_checkbox->Enable(td_adjustment && !td_effective_alpha);
if (m_top_surface_contoning_td_correction_choice != nullptr) {
m_top_surface_contoning_td_correction_choice->Show(contoning);
m_top_surface_contoning_td_correction_choice->Enable(contoning);
}
if (m_top_surface_contoning_td_effective_alpha_correction_checkbox != nullptr) {
const bool td_adjustment =
contoning &&
m_top_surface_contoning_td_adjustment_checkbox != nullptr &&
m_top_surface_contoning_td_adjustment_checkbox->GetValue();
m_top_surface_contoning_td_effective_alpha_correction_checkbox->Show(contoning);
m_top_surface_contoning_td_effective_alpha_correction_checkbox->Enable(td_adjustment);
if (m_top_surface_contoning_variable_layer_height_compensation_checkbox != nullptr) {
m_top_surface_contoning_variable_layer_height_compensation_checkbox->Show(contoning);
m_top_surface_contoning_variable_layer_height_compensation_checkbox->Enable(contoning);
}
if (m_top_surface_contoning_only_one_perimeter_around_shell_infill_checkbox != nullptr) {
m_top_surface_contoning_only_one_perimeter_around_shell_infill_checkbox->Show(contoning);
@@ -4646,10 +4685,9 @@ private:
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};
wxCheckBox *m_top_surface_contoning_beer_lambert_rgb_correction_checkbox {nullptr};
wxCheckBox *m_top_surface_contoning_td_effective_alpha_correction_checkbox {nullptr};
wxChoice *m_top_surface_contoning_td_correction_choice {nullptr};
wxCheckBox *m_top_surface_contoning_variable_layer_height_compensation_checkbox {nullptr};
wxCheckBox *m_use_legacy_fixed_color_mode_checkbox {nullptr};
wxCheckBox *m_minimum_visibility_offset_checkbox {nullptr};
wxSpinCtrl *m_minimum_visibility_offset_spin {nullptr};
@@ -9684,8 +9722,10 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
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_color_prediction_mode,
updated.top_surface_contoning_beer_lambert_rgb_correction_enabled,
updated.top_surface_contoning_td_effective_alpha_correction_enabled,
updated.top_surface_contoning_variable_layer_height_compensation_enabled,
shell_usage,
bundle->texture_mapping_zones,
bundle->texture_mapping_global_settings,
@@ -9772,10 +9812,14 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager)
dlg.top_surface_contoning_td_adjustment_enabled();
updated.top_surface_contoning_surface_scatter_enabled =
dlg.top_surface_contoning_surface_scatter_enabled();
updated.top_surface_contoning_color_prediction_mode =
dlg.top_surface_contoning_color_prediction_mode();
updated.top_surface_contoning_beer_lambert_rgb_correction_enabled =
dlg.top_surface_contoning_beer_lambert_rgb_correction_enabled();
updated.top_surface_contoning_td_effective_alpha_correction_enabled =
dlg.top_surface_contoning_td_effective_alpha_correction_enabled();
updated.top_surface_contoning_variable_layer_height_compensation_enabled =
dlg.top_surface_contoning_variable_layer_height_compensation_enabled();
if (updated.top_surface_image_printing_enabled &&
updated.top_surface_image_printing_method == int(TextureMappingZone::TopSurfaceImageContoning)) {
updated.modulation_mode = int(TextureMappingZone::ModulationPerimeterPathV2);