Use round-trip opacity for TD calibration to improve accuracy
- Use trilinear sampling for color LUT
This commit is contained in:
@@ -137,11 +137,8 @@ const LutImage *lut_image()
|
||||
return image.loaded ? &image : nullptr;
|
||||
}
|
||||
|
||||
std::array<float, 3> sample_lut(const LutImage &image, const std::array<float, 3> &color, int z_offset)
|
||||
std::array<float, 3> sample_lut_texel(const LutImage &image, int x, int y, int z)
|
||||
{
|
||||
const int x = int(std::floor(clamp01(color[0]) * float(k_lut_dimen - 1)));
|
||||
const int y = int(std::floor(clamp01(color[1]) * float(k_lut_dimen - 1)));
|
||||
const int z = int(std::floor(clamp01(color[2]) * float(k_lut_dimen - 1))) + z_offset;
|
||||
const int col = z % image.row_size;
|
||||
const int row = z / image.row_size;
|
||||
const int ix = x + col * k_lut_dimen;
|
||||
@@ -155,6 +152,50 @@ std::array<float, 3> sample_lut(const LutImage &image, const std::array<float, 3
|
||||
};
|
||||
}
|
||||
|
||||
std::array<float, 3> lerp_color(const std::array<float, 3> &a, const std::array<float, 3> &b, float t)
|
||||
{
|
||||
return {
|
||||
a[0] + (b[0] - a[0]) * t,
|
||||
a[1] + (b[1] - a[1]) * t,
|
||||
a[2] + (b[2] - a[2]) * t
|
||||
};
|
||||
}
|
||||
|
||||
std::array<float, 3> sample_lut(const LutImage &image, const std::array<float, 3> &color, int z_offset)
|
||||
{
|
||||
const float xf = clamp01(color[0]) * float(k_lut_dimen - 1);
|
||||
const float yf = clamp01(color[1]) * float(k_lut_dimen - 1);
|
||||
const float zf = clamp01(color[2]) * float(k_lut_dimen - 1);
|
||||
|
||||
const int x0 = int(std::floor(xf));
|
||||
const int y0 = int(std::floor(yf));
|
||||
const int z0 = int(std::floor(zf));
|
||||
const int x1 = std::min(x0 + 1, k_lut_dimen - 1);
|
||||
const int y1 = std::min(y0 + 1, k_lut_dimen - 1);
|
||||
const int z1 = std::min(z0 + 1, k_lut_dimen - 1);
|
||||
|
||||
const float tx = xf - float(x0);
|
||||
const float ty = yf - float(y0);
|
||||
const float tz = zf - float(z0);
|
||||
|
||||
const std::array<float, 3> c000 = sample_lut_texel(image, x0, y0, z0 + z_offset);
|
||||
const std::array<float, 3> c100 = sample_lut_texel(image, x1, y0, z0 + z_offset);
|
||||
const std::array<float, 3> c010 = sample_lut_texel(image, x0, y1, z0 + z_offset);
|
||||
const std::array<float, 3> c110 = sample_lut_texel(image, x1, y1, z0 + z_offset);
|
||||
const std::array<float, 3> c001 = sample_lut_texel(image, x0, y0, z1 + z_offset);
|
||||
const std::array<float, 3> c101 = sample_lut_texel(image, x1, y0, z1 + z_offset);
|
||||
const std::array<float, 3> c011 = sample_lut_texel(image, x0, y1, z1 + z_offset);
|
||||
const std::array<float, 3> c111 = sample_lut_texel(image, x1, y1, z1 + z_offset);
|
||||
|
||||
const std::array<float, 3> c00 = lerp_color(c000, c100, tx);
|
||||
const std::array<float, 3> c10 = lerp_color(c010, c110, tx);
|
||||
const std::array<float, 3> c01 = lerp_color(c001, c101, tx);
|
||||
const std::array<float, 3> c11 = lerp_color(c011, c111, tx);
|
||||
const std::array<float, 3> c0 = lerp_color(c00, c10, ty);
|
||||
const std::array<float, 3> c1 = lerp_color(c01, c11, ty);
|
||||
return lerp_color(c0, c1, tz);
|
||||
}
|
||||
|
||||
std::array<float, 4> color_to_pigment(const LutImage &image, const std::array<float, 3> &color)
|
||||
{
|
||||
const std::array<float, 3> sampled = sample_lut(image, color, 0);
|
||||
|
||||
@@ -344,7 +344,8 @@ ColorSolverNearestResult nearest_color_solver_candidates_perceptual(const Candid
|
||||
std::array<float, 3> mix_ordered_stack_with_buffers(const std::vector<std::array<float, 3>> &colors_with_background,
|
||||
std::vector<float> &weights,
|
||||
const std::vector<uint16_t> &surface_to_deep,
|
||||
const std::vector<float> &layer_opacities)
|
||||
const std::vector<float> &layer_opacities,
|
||||
float surface_scatter)
|
||||
{
|
||||
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();
|
||||
@@ -352,13 +353,20 @@ std::array<float, 3> mix_ordered_stack_with_buffers(const std::vector<std::array
|
||||
const size_t component_count = colors_with_background.size() - 1;
|
||||
weights.assign(colors_with_background.size(), 0.f);
|
||||
float transmission = 1.f;
|
||||
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) {
|
||||
if (size_t(component_idx) >= component_count)
|
||||
continue;
|
||||
const float opacity =
|
||||
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;
|
||||
if (surface_layer) {
|
||||
opacity = std::clamp(safe_surface_scatter + (1.f - safe_surface_scatter) * opacity, 1e-4f, 0.9999f);
|
||||
surface_layer = false;
|
||||
}
|
||||
weights[size_t(component_idx)] += transmission * opacity;
|
||||
transmission *= 1.f - opacity;
|
||||
if (transmission <= 1e-5f)
|
||||
@@ -533,7 +541,8 @@ void append_ordered_stack_candidate(ColorSolverOrderedStackCandidateSet &c
|
||||
std::vector<float> &weights,
|
||||
const std::vector<uint16_t> &surface_to_deep,
|
||||
const std::vector<float> &layer_opacities,
|
||||
int simulated_stack_depth)
|
||||
int simulated_stack_depth,
|
||||
float surface_scatter)
|
||||
{
|
||||
std::vector<uint16_t> simulated_surface_to_deep;
|
||||
const std::vector<uint16_t> *mix_stack = &surface_to_deep;
|
||||
@@ -542,7 +551,7 @@ void append_ordered_stack_candidate(ColorSolverOrderedStackCandidateSet &c
|
||||
mix_stack = &simulated_surface_to_deep;
|
||||
}
|
||||
const std::array<float, 3> mixed =
|
||||
mix_ordered_stack_with_buffers(colors_with_background, weights, *mix_stack, layer_opacities);
|
||||
mix_ordered_stack_with_buffers(colors_with_background, weights, *mix_stack, layer_opacities, surface_scatter);
|
||||
const std::array<float, 3> perceptual = oklab_from_srgb(mixed);
|
||||
candidates.rgbs.emplace_back(mixed[0]);
|
||||
candidates.rgbs.emplace_back(mixed[1]);
|
||||
@@ -615,7 +624,8 @@ std::array<float, 3> mix_color_solver_ordered_stack(const std::vector<std::array
|
||||
const std::vector<uint16_t> &surface_to_deep,
|
||||
const std::vector<float> &layer_opacities,
|
||||
const std::array<float, 3> &background_rgb,
|
||||
ColorSolverMixModel mix_model)
|
||||
ColorSolverMixModel mix_model,
|
||||
float surface_scatter)
|
||||
{
|
||||
(void) mix_model;
|
||||
if (component_colors.empty() || surface_to_deep.empty())
|
||||
@@ -624,7 +634,7 @@ std::array<float, 3> mix_color_solver_ordered_stack(const std::vector<std::array
|
||||
std::vector<std::array<float, 3>> colors = component_colors;
|
||||
colors.emplace_back(background_rgb);
|
||||
std::vector<float> weights;
|
||||
return mix_ordered_stack_with_buffers(colors, weights, surface_to_deep, layer_opacities);
|
||||
return mix_ordered_stack_with_buffers(colors, weights, surface_to_deep, layer_opacities, surface_scatter);
|
||||
}
|
||||
|
||||
std::array<float, 3> color_solver_oklab_from_srgb(const std::array<float, 3> &rgb)
|
||||
@@ -757,7 +767,8 @@ std::string color_solver_ordered_stack_candidate_cache_key(const std::vector<std
|
||||
int stack_depth,
|
||||
int simulated_stack_depth,
|
||||
size_t candidate_limit,
|
||||
size_t stack_item_limit)
|
||||
size_t stack_item_limit,
|
||||
float surface_scatter)
|
||||
{
|
||||
std::ostringstream key;
|
||||
key << component_colors.size();
|
||||
@@ -766,6 +777,9 @@ std::string color_solver_ordered_stack_candidate_cache_key(const std::vector<std
|
||||
key << "|vd" << simulated_stack_depth;
|
||||
key << "|lim" << candidate_limit;
|
||||
key << "|item" << stack_item_limit;
|
||||
const float safe_surface_scatter =
|
||||
std::clamp(std::isfinite(surface_scatter) ? surface_scatter : 0.f, 0.f, 0.5f);
|
||||
key << "|ss" << int(std::lround(safe_surface_scatter * 1000000.f));
|
||||
key << "|bg"
|
||||
<< int(std::lround(clamp01(background_rgb[0]) * 65535.f)) << ','
|
||||
<< int(std::lround(clamp01(background_rgb[1]) * 65535.f)) << ','
|
||||
@@ -795,7 +809,8 @@ ColorSolverOrderedStackCandidateSet build_color_solver_ordered_stack_candidates(
|
||||
int stack_depth,
|
||||
int simulated_stack_depth,
|
||||
size_t candidate_limit,
|
||||
size_t stack_item_limit)
|
||||
size_t stack_item_limit,
|
||||
float surface_scatter)
|
||||
{
|
||||
(void) mix_model;
|
||||
ColorSolverOrderedStackCandidateSet candidates;
|
||||
@@ -832,7 +847,8 @@ ColorSolverOrderedStackCandidateSet build_color_solver_ordered_stack_candidates(
|
||||
weights,
|
||||
surface_to_deep,
|
||||
layer_opacities,
|
||||
simulated_depth);
|
||||
simulated_depth,
|
||||
surface_scatter);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -878,7 +894,8 @@ ColorSolverOrderedStackCandidateSet build_color_solver_ordered_stack_candidates(
|
||||
weights,
|
||||
surface_to_deep,
|
||||
layer_opacities,
|
||||
simulated_depth);
|
||||
simulated_depth,
|
||||
surface_scatter);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -904,7 +921,8 @@ const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates
|
||||
int stack_depth,
|
||||
int simulated_stack_depth,
|
||||
size_t candidate_limit,
|
||||
size_t stack_item_limit)
|
||||
size_t stack_item_limit,
|
||||
float surface_scatter)
|
||||
{
|
||||
const std::string key =
|
||||
color_solver_ordered_stack_candidate_cache_key(component_colors,
|
||||
@@ -914,7 +932,8 @@ const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates
|
||||
stack_depth,
|
||||
simulated_stack_depth,
|
||||
candidate_limit,
|
||||
stack_item_limit);
|
||||
stack_item_limit,
|
||||
surface_scatter);
|
||||
auto it = cache.find(key);
|
||||
if (it != cache.end())
|
||||
return it->second;
|
||||
@@ -927,7 +946,8 @@ const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates
|
||||
stack_depth,
|
||||
simulated_stack_depth,
|
||||
candidate_limit,
|
||||
stack_item_limit)).first->second;
|
||||
stack_item_limit,
|
||||
surface_scatter)).first->second;
|
||||
}
|
||||
|
||||
std::vector<uint16_t> solve_color_solver_ordered_stack_for_target(
|
||||
|
||||
@@ -109,7 +109,8 @@ std::array<float, 3> mix_color_solver_ordered_stack(const std::vector<std::array
|
||||
const std::vector<uint16_t> &surface_to_deep,
|
||||
const std::vector<float> &layer_opacities,
|
||||
const std::array<float, 3> &background_rgb,
|
||||
ColorSolverMixModel mix_model);
|
||||
ColorSolverMixModel mix_model,
|
||||
float surface_scatter = 0.f);
|
||||
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);
|
||||
|
||||
@@ -134,7 +135,8 @@ std::string color_solver_ordered_stack_candidate_cache_key(const std::vector<std
|
||||
int stack_depth,
|
||||
int simulated_stack_depth = 0,
|
||||
size_t candidate_limit = 0,
|
||||
size_t stack_item_limit = 0);
|
||||
size_t stack_item_limit = 0,
|
||||
float surface_scatter = 0.f);
|
||||
ColorSolverOrderedStackCandidateSet build_color_solver_ordered_stack_candidates(
|
||||
const std::vector<std::array<float, 3>> &component_colors,
|
||||
const std::vector<float> &layer_opacities,
|
||||
@@ -143,7 +145,8 @@ ColorSolverOrderedStackCandidateSet build_color_solver_ordered_stack_candidates(
|
||||
int stack_depth,
|
||||
int simulated_stack_depth = 0,
|
||||
size_t candidate_limit = 0,
|
||||
size_t stack_item_limit = 0);
|
||||
size_t stack_item_limit = 0,
|
||||
float surface_scatter = 0.f);
|
||||
const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates(
|
||||
ColorSolverOrderedStackCandidateCache &cache,
|
||||
const std::vector<std::array<float, 3>> &component_colors,
|
||||
@@ -153,7 +156,8 @@ const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates
|
||||
int stack_depth,
|
||||
int simulated_stack_depth = 0,
|
||||
size_t candidate_limit = 0,
|
||||
size_t stack_item_limit = 0);
|
||||
size_t stack_item_limit = 0,
|
||||
float surface_scatter = 0.f);
|
||||
std::vector<uint16_t> solve_color_solver_ordered_stack_for_target(
|
||||
const ColorSolverOrderedStackCandidateSet &candidates,
|
||||
const std::array<float, 3> &target_rgb,
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace {
|
||||
|
||||
constexpr float OPAQUE_CONTONING_TD_THRESHOLD_MM = 0.5f;
|
||||
constexpr float INFERRED_BLACK_TD_MM = 0.1f;
|
||||
constexpr float CONTONING_SURFACE_SCATTER = 0.12f;
|
||||
constexpr size_t MAX_TD_ORDERED_CONTONING_CANDIDATES = 2500000;
|
||||
constexpr size_t MAX_TD_ORDERED_CONTONING_STACK_ITEMS = 20000000;
|
||||
|
||||
@@ -114,7 +115,7 @@ float layer_opacity_from_td(float td_mm, float layer_height_mm)
|
||||
{
|
||||
const float safe_td = std::clamp(td_mm, 0.01f, 50.f);
|
||||
const float safe_layer_height = std::clamp(layer_height_mm, 0.01f, 2.f);
|
||||
return std::clamp(1.f - std::pow(0.05f, safe_layer_height / safe_td), 1e-4f, 0.9999f);
|
||||
return std::clamp(1.f - std::pow(0.05f, 2.f * safe_layer_height / safe_td), 1e-4f, 0.9999f);
|
||||
}
|
||||
|
||||
float effective_transmission_distance_for_component(const std::vector<unsigned int> &component_ids,
|
||||
@@ -354,6 +355,7 @@ TextureMappingContoningSolver::TextureMappingContoningSolver(const TextureMappin
|
||||
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;
|
||||
m_surface_scatter = CONTONING_SURFACE_SCATTER;
|
||||
|
||||
component_ids.erase(std::remove_if(component_ids.begin(), component_ids.end(), [&config](unsigned int id) {
|
||||
return id == 0 || id > config.filament_colour.values.size();
|
||||
@@ -480,7 +482,8 @@ std::optional<std::array<float, 3>> TextureMappingContoningSolver::stack_rgb(
|
||||
surface_to_deep,
|
||||
m_component_layer_opacity,
|
||||
m_background_rgb,
|
||||
ColorSolverMixModel::PigmentPainter);
|
||||
ColorSolverMixModel::PigmentPainter,
|
||||
m_surface_scatter);
|
||||
}
|
||||
|
||||
void TextureMappingContoningSolver::arrange_stack_for_light_path(std::vector<unsigned int> &bottom_to_top,
|
||||
@@ -579,7 +582,8 @@ TextureMappingContoningStack TextureMappingContoningSolver::solve(const std::arr
|
||||
depth,
|
||||
visible_depth,
|
||||
MAX_TD_ORDERED_CONTONING_CANDIDATES,
|
||||
MAX_TD_ORDERED_CONTONING_STACK_ITEMS);
|
||||
MAX_TD_ORDERED_CONTONING_STACK_ITEMS,
|
||||
m_surface_scatter);
|
||||
}
|
||||
const std::vector<uint16_t> surface_to_deep =
|
||||
solve_color_solver_ordered_stack_for_target(*ordered_candidates, target_rgb, ColorSolverMode::V2);
|
||||
|
||||
@@ -65,6 +65,7 @@ private:
|
||||
std::vector<float> m_effective_transmission_distances_mm;
|
||||
std::vector<float> m_component_layer_opacity;
|
||||
float m_layer_height_mm { 0.2f };
|
||||
float m_surface_scatter { 0.f };
|
||||
bool m_td_adjustment_enabled { false };
|
||||
mutable std::map<int, std::vector<Candidate>> m_candidates_by_depth;
|
||||
mutable std::shared_ptr<ColorSolverOrderedStackCandidateCache> m_ordered_candidate_cache { std::make_shared<ColorSolverOrderedStackCandidateCache>() };
|
||||
|
||||
@@ -50,6 +50,7 @@ constexpr size_t k_contoning_flat_surface_preview_max_ordered_stack_items = 2000
|
||||
constexpr double k_contoning_top_surface_preview_lod_max_samples = 350000.0;
|
||||
constexpr const char *TEXTURE_MAPPING_BACKGROUND_COLOR_CONFIG_KEY = "texture_mapping_background_color";
|
||||
constexpr float k_contoning_preview_inferred_black_td_mm = 0.1f;
|
||||
constexpr float k_contoning_preview_surface_scatter = 0.12f;
|
||||
|
||||
struct TexturePreviewMixCandidate
|
||||
{
|
||||
@@ -98,6 +99,7 @@ struct TexturePreviewSimulationSettings
|
||||
bool simulate_top_surface_lod = false;
|
||||
float top_surface_lod_pitch_mm = 0.f;
|
||||
float contoning_flat_surface_layer_height_mm = 0.2f;
|
||||
float contoning_flat_surface_surface_scatter = k_contoning_preview_surface_scatter;
|
||||
std::array<float, 3> contoning_flat_surface_background_rgb { { 0.f, 0.f, 0.f } };
|
||||
std::vector<float> contoning_flat_surface_layer_opacities;
|
||||
float minimum_visibility_offset_factor = 0.f;
|
||||
@@ -576,7 +578,7 @@ float texture_preview_layer_opacity_from_td(float td_mm, float layer_height_mm)
|
||||
{
|
||||
const float safe_td = std::clamp(td_mm, 0.01f, 50.f);
|
||||
const float safe_layer_height = std::clamp(layer_height_mm, 0.01f, 2.f);
|
||||
return std::clamp(1.f - std::pow(0.05f, safe_layer_height / safe_td), 1e-4f, 0.9999f);
|
||||
return std::clamp(1.f - std::pow(0.05f, 2.f * safe_layer_height / safe_td), 1e-4f, 0.9999f);
|
||||
}
|
||||
|
||||
std::vector<float> contoning_flat_surface_preview_layer_opacities(
|
||||
@@ -2507,7 +2509,8 @@ std::array<float, 3> contoning_flat_surface_rgb_for_texture_preview(
|
||||
simulated_surface_to_deep,
|
||||
settings.contoning_flat_surface_layer_opacities,
|
||||
settings.contoning_flat_surface_background_rgb,
|
||||
ColorSolverMixModel::PigmentPainter);
|
||||
ColorSolverMixModel::PigmentPainter,
|
||||
settings.contoning_flat_surface_surface_scatter);
|
||||
}
|
||||
}
|
||||
if (!candidates.empty()) {
|
||||
@@ -2757,6 +2760,7 @@ size_t texture_preview_simulation_signature(const ModelVolume &model_volume,
|
||||
}
|
||||
if (settings.contoning_flat_surface_td_adjustment) {
|
||||
mix(std::hash<int>{}(int(std::lround(settings.contoning_flat_surface_layer_height_mm * 100000.f))));
|
||||
mix(std::hash<int>{}(int(std::lround(settings.contoning_flat_surface_surface_scatter * 1000000.f))));
|
||||
for (const float opacity : settings.contoning_flat_surface_layer_opacities)
|
||||
mix(std::hash<int>{}(int(std::lround(opacity * 1000000.f))));
|
||||
}
|
||||
@@ -2844,7 +2848,8 @@ TexturePreviewSimulationResult build_simulated_texture_preview_result(size_t sig
|
||||
contoning_flat_surface_pattern_filaments,
|
||||
contoning_flat_surface_pattern_filaments,
|
||||
k_contoning_flat_surface_preview_max_ordered_candidates,
|
||||
k_contoning_flat_surface_preview_max_ordered_stack_items) :
|
||||
k_contoning_flat_surface_preview_max_ordered_stack_items,
|
||||
settings.contoning_flat_surface_surface_scatter) :
|
||||
ColorSolverOrderedStackCandidateSet{};
|
||||
const std::vector<TexturePreviewMixCandidate> contoning_flat_surface_candidates =
|
||||
use_contoning_flat_surface_quantization && contoning_flat_surface_ordered_candidates.empty() ?
|
||||
|
||||
@@ -2309,19 +2309,19 @@ public:
|
||||
filament_root->Add(m_force_sequential_filaments_checkbox, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, gap);
|
||||
|
||||
filament_root->AddStretchSpacer(1);
|
||||
auto *filament_calibration_note =
|
||||
new wxStaticText(filament_page,
|
||||
wxID_ANY,
|
||||
_L("NOTE: TD calibration is used by overhang modulation and Contoning TD adjustment"),
|
||||
wxDefaultPosition,
|
||||
wxSize(FromDIP(390), -1));
|
||||
filament_calibration_note->Wrap(FromDIP(390));
|
||||
filament_root->Add(filament_calibration_note, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, gap);
|
||||
filament_page->Bind(wxEVT_SIZE, [this, filament_page, filament_calibration_note, gap](wxSizeEvent &evt) {
|
||||
const int wrap_width = std::max(FromDIP(120), filament_page->GetClientSize().GetWidth() - gap * 2);
|
||||
filament_calibration_note->Wrap(wrap_width);
|
||||
evt.Skip();
|
||||
});
|
||||
// auto *filament_calibration_note =
|
||||
// new wxStaticText(filament_page,
|
||||
// wxID_ANY,
|
||||
// _L("NOTE: TD calibration is used by overhang modulation and Contoning TD adjustment"),
|
||||
// wxDefaultPosition,
|
||||
// wxSize(FromDIP(390), -1));
|
||||
// filament_calibration_note->Wrap(FromDIP(390));
|
||||
// filament_root->Add(filament_calibration_note, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, gap);
|
||||
// filament_page->Bind(wxEVT_SIZE, [this, filament_page, filament_calibration_note, gap](wxSizeEvent &evt) {
|
||||
// const int wrap_width = std::max(FromDIP(120), filament_page->GetClientSize().GetWidth() - gap * 2);
|
||||
// filament_calibration_note->Wrap(wrap_width);
|
||||
// evt.Skip();
|
||||
// });
|
||||
|
||||
auto *preview_box = new wxStaticBoxSizer(wxVERTICAL, preview_page, _L("3D Preview"));
|
||||
auto *preview_opacity_row = new wxBoxSizer(wxHORIZONTAL);
|
||||
@@ -3779,7 +3779,11 @@ private:
|
||||
return 0;
|
||||
const float layer_height = top_surface_contoning_layer_height_mm();
|
||||
const float safe_strength = std::clamp(strength, 0.01f, 0.99f);
|
||||
const float layers = (td_mm / layer_height) * (std::log(1.f - safe_strength) / std::log(0.05f));
|
||||
constexpr float surface_scatter = 0.12f;
|
||||
if (safe_strength <= surface_scatter)
|
||||
return 1;
|
||||
const float remaining = std::clamp((1.f - safe_strength) / (1.f - surface_scatter), 1e-6f, 0.999999f);
|
||||
const float layers = (td_mm / (2.f * layer_height)) * (std::log(remaining) / std::log(0.05f));
|
||||
return std::max(1, int(std::ceil(layers)));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user