Optimizations for sampling step during slicing. Disable surface scatter correction when TD Effective Alpha is enabled
This commit is contained in:
@@ -670,7 +670,7 @@ std::array<float, 3> mix_ordered_stack_with_buffers(const std::vector<std::array
|
||||
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, surface_scatter, component_roles);
|
||||
return mix_ordered_stack_td_effective_alpha(colors_with_background, surface_to_deep, layer_opacities, 0.f, component_roles);
|
||||
if (beer_lambert_rgb_correction)
|
||||
return mix_ordered_stack_beer_lambert_rgb(colors_with_background, surface_to_deep, layer_opacities, surface_scatter);
|
||||
|
||||
@@ -1273,7 +1273,9 @@ std::string color_solver_ordered_stack_candidate_cache_key(const std::vector<std
|
||||
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);
|
||||
td_effective_alpha_correction ?
|
||||
0.f :
|
||||
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 << "|bl" << (beer_lambert_rgb_correction ? 1 : 0);
|
||||
key << "|ea" << (td_effective_alpha_correction ? 1 : 0);
|
||||
@@ -1481,13 +1483,15 @@ const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates
|
||||
beam_search_stack_expansion)).first->second;
|
||||
}
|
||||
|
||||
std::vector<uint16_t> solve_color_solver_ordered_stack_for_target(
|
||||
ColorSolverOrderedStackResult solve_color_solver_ordered_stack_result_for_target(
|
||||
const ColorSolverOrderedStackCandidateSet &candidates,
|
||||
const std::array<float, 3> &target_rgb,
|
||||
ColorSolverMode solver_mode)
|
||||
{
|
||||
ColorSolverOrderedStackResult result;
|
||||
|
||||
if (candidates.empty())
|
||||
return {};
|
||||
return result;
|
||||
|
||||
const size_t candidate_count = candidates.rgbs.size() / 3;
|
||||
ColorSolverNearestResult nearest =
|
||||
@@ -1497,13 +1501,34 @@ std::vector<uint16_t> solve_color_solver_ordered_stack_for_target(
|
||||
if (nearest.best_idx >= candidate_count && color_solver_mode_is_perceptual(solver_mode))
|
||||
nearest = nearest_color_solver_candidates(candidates, target_rgb);
|
||||
if (nearest.best_idx >= candidate_count)
|
||||
return {};
|
||||
return result;
|
||||
|
||||
const size_t stack_begin = nearest.best_idx * size_t(candidates.stack_depth);
|
||||
if (stack_begin + size_t(candidates.stack_depth) > candidates.stacks.size())
|
||||
return {};
|
||||
return std::vector<uint16_t>(candidates.stacks.begin() + stack_begin,
|
||||
candidates.stacks.begin() + stack_begin + candidates.stack_depth);
|
||||
return result;
|
||||
|
||||
result.surface_to_deep = std::vector<uint16_t>(candidates.stacks.begin() + stack_begin,
|
||||
candidates.stacks.begin() + stack_begin + candidates.stack_depth);
|
||||
|
||||
const size_t rgb_begin = nearest.best_idx * 3;
|
||||
if (rgb_begin + 2 < candidates.rgbs.size()) {
|
||||
result.rgb = { {
|
||||
candidates.rgbs[rgb_begin + 0],
|
||||
candidates.rgbs[rgb_begin + 1],
|
||||
candidates.rgbs[rgb_begin + 2],
|
||||
} };
|
||||
result.has_rgb = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<uint16_t> solve_color_solver_ordered_stack_for_target(
|
||||
const ColorSolverOrderedStackCandidateSet &candidates,
|
||||
const std::array<float, 3> &target_rgb,
|
||||
ColorSolverMode solver_mode)
|
||||
{
|
||||
return solve_color_solver_ordered_stack_result_for_target(candidates, target_rgb, solver_mode).surface_to_deep;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -102,6 +102,12 @@ struct ColorSolverOrderedStackCandidateSet {
|
||||
}
|
||||
};
|
||||
|
||||
struct ColorSolverOrderedStackResult {
|
||||
std::vector<uint16_t> surface_to_deep;
|
||||
std::array<float, 3> rgb { { 0.f, 0.f, 0.f } };
|
||||
bool has_rgb { false };
|
||||
};
|
||||
|
||||
using ColorSolverOrderedStackCandidateCache = std::map<std::string, ColorSolverOrderedStackCandidateSet>;
|
||||
|
||||
ColorSolverMixModel color_solver_mix_model_from_index(int model);
|
||||
@@ -185,6 +191,10 @@ const ColorSolverOrderedStackCandidateSet &color_solver_ordered_stack_candidates
|
||||
bool td_effective_alpha_correction = false,
|
||||
const std::vector<ColorSolverStackComponentRole> &component_roles = {},
|
||||
bool beam_search_stack_expansion = false);
|
||||
ColorSolverOrderedStackResult solve_color_solver_ordered_stack_result_for_target(
|
||||
const ColorSolverOrderedStackCandidateSet &candidates,
|
||||
const std::array<float, 3> &target_rgb,
|
||||
ColorSolverMode solver_mode);
|
||||
std::vector<uint16_t> solve_color_solver_ordered_stack_for_target(
|
||||
const ColorSolverOrderedStackCandidateSet &candidates,
|
||||
const std::array<float, 3> &target_rgb,
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "libslic3r.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cctype>
|
||||
#include <cstdint>
|
||||
#include <chrono>
|
||||
@@ -2004,7 +2005,14 @@ struct TopSurfaceImageContoningAnchoredSurfacePlan {
|
||||
std::vector<TopSurfaceImageContoningAnchoredSurfaceRegion> regions;
|
||||
};
|
||||
|
||||
class TopSurfaceImageContoningAnchoredDepthWork
|
||||
class TopSurfaceImageContoningAnchoredWork
|
||||
{
|
||||
public:
|
||||
virtual ~TopSurfaceImageContoningAnchoredWork() = default;
|
||||
virtual bool run_one() = 0;
|
||||
};
|
||||
|
||||
class TopSurfaceImageContoningAnchoredDepthWork : public TopSurfaceImageContoningAnchoredWork
|
||||
{
|
||||
public:
|
||||
using BuildFn = std::function<std::vector<TopSurfaceImageContoningVectorRegion>(int)>;
|
||||
@@ -2021,7 +2029,7 @@ public:
|
||||
, m_progress(std::move(progress))
|
||||
{}
|
||||
|
||||
bool run_one()
|
||||
bool run_one() override
|
||||
{
|
||||
int depth = -1;
|
||||
{
|
||||
@@ -2081,41 +2089,112 @@ private:
|
||||
std::exception_ptr m_error;
|
||||
};
|
||||
|
||||
class TopSurfaceImageContoningAnchoredIndexWork : public TopSurfaceImageContoningAnchoredWork
|
||||
{
|
||||
public:
|
||||
using RunFn = std::function<void(size_t)>;
|
||||
using ProgressFn = std::function<void(size_t)>;
|
||||
|
||||
TopSurfaceImageContoningAnchoredIndexWork(size_t count, RunFn run, ProgressFn progress)
|
||||
: m_count(count)
|
||||
, m_run(std::move(run))
|
||||
, m_progress(std::move(progress))
|
||||
{
|
||||
m_done = m_count == 0;
|
||||
}
|
||||
|
||||
bool run_one() override
|
||||
{
|
||||
size_t idx = 0;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (m_error || m_next >= m_count)
|
||||
return false;
|
||||
idx = m_next++;
|
||||
++m_active;
|
||||
}
|
||||
|
||||
std::exception_ptr error;
|
||||
try {
|
||||
m_run(idx);
|
||||
} catch (...) {
|
||||
error = std::current_exception();
|
||||
}
|
||||
|
||||
size_t completed = 0;
|
||||
bool done = false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (error && !m_error)
|
||||
m_error = error;
|
||||
--m_active;
|
||||
completed = ++m_completed;
|
||||
done = (m_error || m_next >= m_count) && m_active == 0;
|
||||
m_done = m_done || done;
|
||||
}
|
||||
if (done)
|
||||
m_cv.notify_all();
|
||||
if (!error && m_progress)
|
||||
m_progress(completed);
|
||||
return true;
|
||||
}
|
||||
|
||||
void wait()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
m_cv.wait(lock, [this]() { return m_done; });
|
||||
if (m_error)
|
||||
std::rethrow_exception(m_error);
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_cv;
|
||||
size_t m_count { 0 };
|
||||
RunFn m_run;
|
||||
ProgressFn m_progress;
|
||||
size_t m_next { 0 };
|
||||
int m_active { 0 };
|
||||
size_t m_completed { 0 };
|
||||
bool m_done { false };
|
||||
std::exception_ptr m_error;
|
||||
};
|
||||
|
||||
class TopSurfaceImageContoningAnchoredSurfaceBuildState
|
||||
{
|
||||
public:
|
||||
void set_depth_work(std::shared_ptr<TopSurfaceImageContoningAnchoredDepthWork> work)
|
||||
void set_work(std::shared_ptr<TopSurfaceImageContoningAnchoredWork> work)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (!m_finished)
|
||||
m_depth_work = std::move(work);
|
||||
m_work = std::move(work);
|
||||
}
|
||||
m_cv.notify_all();
|
||||
}
|
||||
|
||||
void clear_depth_work(const std::shared_ptr<TopSurfaceImageContoningAnchoredDepthWork> &work)
|
||||
void clear_work(const std::shared_ptr<TopSurfaceImageContoningAnchoredWork> &work)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (m_depth_work == work)
|
||||
m_depth_work.reset();
|
||||
if (m_work == work)
|
||||
m_work.reset();
|
||||
}
|
||||
m_cv.notify_all();
|
||||
}
|
||||
|
||||
bool help_one()
|
||||
{
|
||||
std::shared_ptr<TopSurfaceImageContoningAnchoredDepthWork> work;
|
||||
std::shared_ptr<TopSurfaceImageContoningAnchoredWork> work;
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
if (!m_finished && !m_depth_work)
|
||||
if (!m_finished && !m_work)
|
||||
m_cv.wait_for(lock, std::chrono::milliseconds(2), [this]() {
|
||||
return m_finished || m_depth_work != nullptr;
|
||||
return m_finished || m_work != nullptr;
|
||||
});
|
||||
if (m_finished || !m_depth_work)
|
||||
if (m_finished || !m_work)
|
||||
return false;
|
||||
work = m_depth_work;
|
||||
work = m_work;
|
||||
}
|
||||
return work->run_one();
|
||||
}
|
||||
@@ -2125,7 +2204,7 @@ public:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_finished = true;
|
||||
m_depth_work.reset();
|
||||
m_work.reset();
|
||||
}
|
||||
m_cv.notify_all();
|
||||
}
|
||||
@@ -2133,7 +2212,7 @@ public:
|
||||
private:
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_cv;
|
||||
std::shared_ptr<TopSurfaceImageContoningAnchoredDepthWork> m_depth_work;
|
||||
std::shared_ptr<TopSurfaceImageContoningAnchoredWork> m_work;
|
||||
bool m_finished { false };
|
||||
};
|
||||
|
||||
@@ -3995,6 +4074,53 @@ static std::optional<TopSurfaceImageContoningCellSample> top_surface_image_conto
|
||||
return out;
|
||||
}
|
||||
|
||||
static std::optional<TopSurfaceImageContoningSolvedLabel> top_surface_image_contoning_label_for_stack(
|
||||
const TextureMappingContoningStack &stack,
|
||||
const TextureMappingContoningSolver &solver,
|
||||
bool lower_surface,
|
||||
int visible_layers,
|
||||
std::vector<TopSurfaceImageContoningVectorLabel> &labels,
|
||||
std::map<std::pair<std::vector<unsigned int>, int>, int> &label_by_stack)
|
||||
{
|
||||
if (stack.bottom_to_top.empty())
|
||||
return std::nullopt;
|
||||
const auto label_key = std::make_pair(stack.bottom_to_top, std::max(0, visible_layers));
|
||||
auto label_it = label_by_stack.find(label_key);
|
||||
int label = -1;
|
||||
std::optional<std::array<float, 3>> stack_rgb;
|
||||
if (label_it != label_by_stack.end()) {
|
||||
label = label_it->second;
|
||||
if (label >= 0 && label < int(labels.size()))
|
||||
stack_rgb = labels[size_t(label)].rgb;
|
||||
else {
|
||||
label_by_stack.erase(label_it);
|
||||
label = -1;
|
||||
}
|
||||
}
|
||||
if (!stack_rgb) {
|
||||
if (stack.rgb)
|
||||
stack_rgb = stack.rgb;
|
||||
else
|
||||
stack_rgb = solver.stack_rgb(stack.bottom_to_top, lower_surface, visible_layers);
|
||||
if (!stack_rgb)
|
||||
return std::nullopt;
|
||||
|
||||
TopSurfaceImageContoningVectorLabel label_data;
|
||||
label_data.bottom_to_top = stack.bottom_to_top;
|
||||
label_data.rgb = *stack_rgb;
|
||||
label_data.oklab = color_solver_oklab_from_srgb(*stack_rgb);
|
||||
label_data.valid_depth = std::max(visible_layers, int(stack.bottom_to_top.size()));
|
||||
label_data.repeat_allowed = visible_layers > int(stack.bottom_to_top.size());
|
||||
label = int(labels.size());
|
||||
labels.emplace_back(std::move(label_data));
|
||||
label_by_stack.emplace(label_key, label);
|
||||
}
|
||||
TopSurfaceImageContoningSolvedLabel out;
|
||||
out.label = label;
|
||||
out.rgb = *stack_rgb;
|
||||
return out;
|
||||
}
|
||||
|
||||
static std::optional<TopSurfaceImageContoningSolvedLabel> top_surface_image_contoning_solve_label(
|
||||
const std::array<float, 3> &rgb,
|
||||
int solve_layers,
|
||||
@@ -4005,32 +4131,7 @@ static std::optional<TopSurfaceImageContoningSolvedLabel> top_surface_image_cont
|
||||
std::map<std::pair<std::vector<unsigned int>, int>, int> &label_by_stack)
|
||||
{
|
||||
TextureMappingContoningStack stack = solver.solve(rgb, solve_layers, lower_surface, visible_layers);
|
||||
if (stack.bottom_to_top.empty())
|
||||
return std::nullopt;
|
||||
std::optional<std::array<float, 3>> stack_rgb =
|
||||
solver.stack_rgb(stack.bottom_to_top, lower_surface, visible_layers);
|
||||
if (!stack_rgb)
|
||||
return std::nullopt;
|
||||
const auto label_key = std::make_pair(stack.bottom_to_top, std::max(0, visible_layers));
|
||||
auto label_it = label_by_stack.find(label_key);
|
||||
int label = -1;
|
||||
if (label_it == label_by_stack.end()) {
|
||||
TopSurfaceImageContoningVectorLabel label_data;
|
||||
label_data.bottom_to_top = stack.bottom_to_top;
|
||||
label_data.rgb = *stack_rgb;
|
||||
label_data.oklab = color_solver_oklab_from_srgb(*stack_rgb);
|
||||
label_data.valid_depth = std::max(visible_layers, int(stack.bottom_to_top.size()));
|
||||
label_data.repeat_allowed = visible_layers > int(stack.bottom_to_top.size());
|
||||
label = int(labels.size());
|
||||
labels.emplace_back(std::move(label_data));
|
||||
label_by_stack.emplace(label_key, label);
|
||||
} else {
|
||||
label = label_it->second;
|
||||
}
|
||||
TopSurfaceImageContoningSolvedLabel out;
|
||||
out.label = label;
|
||||
out.rgb = *stack_rgb;
|
||||
return out;
|
||||
return top_surface_image_contoning_label_for_stack(stack, solver, lower_surface, visible_layers, labels, label_by_stack);
|
||||
}
|
||||
|
||||
static void top_surface_image_contoning_resolve_merged_grid_regions(
|
||||
@@ -4263,19 +4364,20 @@ static void top_surface_image_contoning_solve_anchored_region(
|
||||
const int rows = std::max(0, int(std::ceil(double(bbox.max.y() - min_y) / double(step))));
|
||||
if (cols <= 0 || rows <= 0)
|
||||
return;
|
||||
const size_t grid_cells = size_t(cols) * size_t(rows);
|
||||
const int sampling_progress_total = int(std::min<size_t>(grid_cells, size_t(std::numeric_limits<int>::max())));
|
||||
|
||||
top_surface_image_contoning_report_anchored_progress(object,
|
||||
source_layer,
|
||||
source_surface,
|
||||
L("sampling"),
|
||||
0,
|
||||
source_context.stack_layers);
|
||||
sampling_progress_total);
|
||||
|
||||
std::vector<int> grid(size_t(cols) * size_t(rows), -1);
|
||||
std::vector<TopSurfaceImageContoningVectorLabel> labels;
|
||||
std::map<std::pair<std::vector<unsigned int>, int>, int> label_by_stack;
|
||||
|
||||
const size_t grid_cells = size_t(cols) * size_t(rows);
|
||||
const int debug_stride = debug_enabled ?
|
||||
std::max(1, int(std::ceil(std::sqrt(double(grid_cells) / 100000.0)))) :
|
||||
0;
|
||||
@@ -4289,16 +4391,18 @@ static void top_surface_image_contoning_solve_anchored_region(
|
||||
true);
|
||||
}
|
||||
|
||||
auto solve_cell = [&](int row, int col, const std::array<float, 3> &target_rgb, int solve_layers, int available_depth) {
|
||||
const bool lower_surface =
|
||||
source_surface == TopSurfaceImageSourceSurface::Bottom &&
|
||||
plan.contoning_td_adjustment_enabled;
|
||||
|
||||
auto label_cell = [&](int row, int col, const TextureMappingContoningStack &stack, int available_depth) {
|
||||
std::optional<TopSurfaceImageContoningSolvedLabel> solved =
|
||||
top_surface_image_contoning_solve_label(target_rgb,
|
||||
solve_layers,
|
||||
available_depth,
|
||||
solver,
|
||||
source_surface == TopSurfaceImageSourceSurface::Bottom &&
|
||||
plan.contoning_td_adjustment_enabled,
|
||||
labels,
|
||||
label_by_stack);
|
||||
top_surface_image_contoning_label_for_stack(stack,
|
||||
solver,
|
||||
lower_surface,
|
||||
available_depth,
|
||||
labels,
|
||||
label_by_stack);
|
||||
if (!solved)
|
||||
return;
|
||||
grid[size_t(row * cols + col)] = solved->label;
|
||||
@@ -4329,42 +4433,90 @@ static void top_surface_image_contoning_solve_anchored_region(
|
||||
|
||||
std::vector<std::optional<TopSurfaceImageContoningCellSample>> cell_samples(grid.size());
|
||||
std::vector<int> cell_available_depths(grid.size(), 0);
|
||||
size_t debug_sampled_cell_count = 0;
|
||||
std::vector<TextureMappingContoningStack> cell_stacks(grid.size());
|
||||
std::atomic<size_t> debug_sampled_cell_count { 0 };
|
||||
std::mutex debug_sample_area_mutex;
|
||||
const auto debug_sampling_start = top_surface_image_debug_now();
|
||||
for (int row = 0; row < rows; ++row) {
|
||||
if ((row & 15) == 0)
|
||||
auto solve_sampled_cell = [&](size_t grid_idx) {
|
||||
const int row = int(grid_idx / size_t(cols));
|
||||
const int col = int(grid_idx - size_t(row) * size_t(cols));
|
||||
if ((row & 15) == 0 && col == 0)
|
||||
check_canceled(throw_if_canceled);
|
||||
for (int col = 0; col < cols; ++col) {
|
||||
const std::optional<TopSurfaceImageContoningCellSample> sample = sample_cell(row, col);
|
||||
if (!sample)
|
||||
continue;
|
||||
const size_t grid_idx = size_t(row * cols + col);
|
||||
cell_samples[grid_idx] = sample;
|
||||
cell_available_depths[grid_idx] = sample->available_depth;
|
||||
++debug_sampled_cell_count;
|
||||
solve_cell(row, col, sample->rgb, sample->solve_layers, sample->available_depth);
|
||||
if (debug_stride > 0 &&
|
||||
row % debug_stride == 0 &&
|
||||
col % debug_stride == 0) {
|
||||
const coord_t x0 = min_x + coord_t(col) * step;
|
||||
const coord_t y0 = min_y + coord_t(row) * step;
|
||||
const coord_t x1 = std::min<coord_t>(x0 + coord_t(debug_stride) * step, bbox.max.x());
|
||||
const coord_t y1 = std::min<coord_t>(y0 + coord_t(debug_stride) * step, bbox.max.y());
|
||||
if (x1 > x0 && y1 > y0) {
|
||||
TopSurfaceImageContoningDebugSampleArea debug_area;
|
||||
debug_area.rgb = sample->rgb;
|
||||
debug_area.area.emplace_back(top_surface_image_cell_expolygon(x0, y0, x1, y1));
|
||||
const std::optional<TopSurfaceImageContoningCellSample> sample = sample_cell(row, col);
|
||||
if (!sample)
|
||||
return;
|
||||
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);
|
||||
if (debug_stride > 0 &&
|
||||
row % debug_stride == 0 &&
|
||||
col % debug_stride == 0) {
|
||||
const coord_t x0 = min_x + coord_t(col) * step;
|
||||
const coord_t y0 = min_y + coord_t(row) * step;
|
||||
const coord_t x1 = std::min<coord_t>(x0 + coord_t(debug_stride) * step, bbox.max.x());
|
||||
const coord_t y1 = std::min<coord_t>(y0 + coord_t(debug_stride) * step, bbox.max.y());
|
||||
if (x1 > x0 && y1 > y0) {
|
||||
TopSurfaceImageContoningDebugSampleArea debug_area;
|
||||
debug_area.rgb = sample->rgb;
|
||||
debug_area.area.emplace_back(top_surface_image_cell_expolygon(x0, y0, x1, y1));
|
||||
if (debug_enabled) {
|
||||
std::lock_guard<std::mutex> lock(debug_sample_area_mutex);
|
||||
anchored_region.debug_sample_areas.emplace_back(std::move(debug_area));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto report_sampling_progress = [&](size_t completed) {
|
||||
if (completed != grid_cells && (completed & 4095) != 0)
|
||||
return;
|
||||
const int current = int(std::min<size_t>(completed, size_t(sampling_progress_total)));
|
||||
top_surface_image_contoning_report_anchored_progress(object,
|
||||
source_layer,
|
||||
source_surface,
|
||||
L("sampling"),
|
||||
current,
|
||||
sampling_progress_total);
|
||||
};
|
||||
|
||||
std::shared_ptr<TopSurfaceImageContoningAnchoredIndexWork> sample_work =
|
||||
std::make_shared<TopSurfaceImageContoningAnchoredIndexWork>(grid_cells,
|
||||
solve_sampled_cell,
|
||||
report_sampling_progress);
|
||||
if (build_state != nullptr)
|
||||
build_state->set_work(sample_work);
|
||||
try {
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, grid_cells, 32),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t idx = range.begin(); idx != range.end(); ++idx)
|
||||
sample_work->run_one();
|
||||
});
|
||||
sample_work->wait();
|
||||
} catch (...) {
|
||||
if (build_state != nullptr)
|
||||
build_state->clear_work(sample_work);
|
||||
throw;
|
||||
}
|
||||
if (build_state != nullptr)
|
||||
build_state->clear_work(sample_work);
|
||||
|
||||
for (int row = 0; row < rows; ++row) {
|
||||
if ((row & 15) == 0)
|
||||
check_canceled(throw_if_canceled);
|
||||
for (int col = 0; col < cols; ++col) {
|
||||
const size_t grid_idx = size_t(row * cols + col);
|
||||
if (!cell_samples[grid_idx])
|
||||
continue;
|
||||
label_cell(row, col, cell_stacks[grid_idx], cell_samples[grid_idx]->available_depth);
|
||||
}
|
||||
}
|
||||
if (debug_enabled) {
|
||||
debug_timing.sampled_cell_count = debug_sampled_cell_count;
|
||||
debug_timing.sampled_cell_count = debug_sampled_cell_count.load();
|
||||
top_surface_image_debug_accumulate_timing_step(debug_timing.steps,
|
||||
"sample_and_solve_cells",
|
||||
top_surface_image_debug_elapsed_ms(debug_sampling_start),
|
||||
debug_sampled_cell_count,
|
||||
debug_sampled_cell_count.load(),
|
||||
true);
|
||||
}
|
||||
|
||||
@@ -4540,7 +4692,7 @@ static void top_surface_image_contoning_solve_anchored_region(
|
||||
build_depth_regions,
|
||||
store_depth_regions,
|
||||
report_progress);
|
||||
build_state->set_depth_work(depth_work);
|
||||
build_state->set_work(depth_work);
|
||||
try {
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, active_depths.size(), 1),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
@@ -4549,10 +4701,10 @@ static void top_surface_image_contoning_solve_anchored_region(
|
||||
});
|
||||
depth_work->wait();
|
||||
} catch (...) {
|
||||
build_state->clear_depth_work(depth_work);
|
||||
build_state->clear_work(depth_work);
|
||||
throw;
|
||||
}
|
||||
build_state->clear_depth_work(depth_work);
|
||||
build_state->clear_work(depth_work);
|
||||
} else {
|
||||
std::atomic<int> completed_depths { 0 };
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, active_depths.size(), 1),
|
||||
@@ -6124,10 +6276,10 @@ static std::vector<TopSurfaceImageRegionPlan> top_surface_image_region_plans(
|
||||
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;
|
||||
plan.contoning_td_effective_alpha_correction_enabled =
|
||||
plan.contoning_td_adjustment_enabled && zone->top_surface_contoning_td_effective_alpha_correction_enabled;
|
||||
plan.contoning_surface_scatter_enabled =
|
||||
zone->effective_top_surface_contoning_surface_scatter_enabled();
|
||||
plan.contoning_beer_lambert_rgb_correction_enabled =
|
||||
plan.contoning_td_adjustment_enabled &&
|
||||
!plan.contoning_td_effective_alpha_correction_enabled &&
|
||||
|
||||
@@ -1182,7 +1182,7 @@ bool TextureMappingZone::operator==(const TextureMappingZone &rhs) const
|
||||
effective_top_surface_contoning_surface_anchored_stack_optimizations_enabled() ==
|
||||
rhs.effective_top_surface_contoning_surface_anchored_stack_optimizations_enabled() &&
|
||||
top_surface_contoning_td_adjustment_enabled == rhs.top_surface_contoning_td_adjustment_enabled &&
|
||||
top_surface_contoning_surface_scatter_enabled == rhs.top_surface_contoning_surface_scatter_enabled &&
|
||||
effective_top_surface_contoning_surface_scatter_enabled() == rhs.effective_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() &&
|
||||
@@ -1595,7 +1595,7 @@ std::string TextureMappingManager::serialize_entries()
|
||||
texture["top_surface_contoning_td_adjustment_enabled"] =
|
||||
zone.top_surface_contoning_td_adjustment_enabled;
|
||||
texture["top_surface_contoning_surface_scatter_enabled"] =
|
||||
zone.top_surface_contoning_surface_scatter_enabled;
|
||||
zone.effective_top_surface_contoning_surface_scatter_enabled();
|
||||
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"] =
|
||||
|
||||
@@ -322,6 +322,13 @@ struct TextureMappingZone
|
||||
return ShowExperimentalTopSurfaceContoningOptions && value;
|
||||
}
|
||||
|
||||
static bool effective_top_surface_contoning_surface_scatter_enabled(bool td_adjustment,
|
||||
bool surface_scatter,
|
||||
bool td_effective_alpha)
|
||||
{
|
||||
return td_adjustment && surface_scatter && !td_effective_alpha;
|
||||
}
|
||||
|
||||
static bool effective_top_surface_contoning_layer_phase_enabled(bool value, bool surface_anchored_stacks)
|
||||
{
|
||||
return effective_top_surface_contoning_layer_phase_enabled(value) &&
|
||||
@@ -574,6 +581,14 @@ struct TextureMappingZone
|
||||
top_surface_contoning_supersampled_cells_enabled);
|
||||
}
|
||||
|
||||
bool effective_top_surface_contoning_surface_scatter_enabled() const
|
||||
{
|
||||
return TextureMappingZone::effective_top_surface_contoning_surface_scatter_enabled(
|
||||
top_surface_contoning_td_adjustment_enabled,
|
||||
top_surface_contoning_surface_scatter_enabled,
|
||||
top_surface_contoning_td_effective_alpha_correction_enabled);
|
||||
}
|
||||
|
||||
void apply_top_surface_contoning_experimental_defaults()
|
||||
{
|
||||
if (top_surface_image_printing_enabled &&
|
||||
@@ -602,6 +617,8 @@ struct TextureMappingZone
|
||||
top_surface_contoning_layer_phase_enabled = false;
|
||||
top_surface_contoning_blue_noise_error_diffusion_enabled = false;
|
||||
}
|
||||
if (top_surface_contoning_td_effective_alpha_correction_enabled)
|
||||
top_surface_contoning_surface_scatter_enabled = false;
|
||||
}
|
||||
|
||||
void apply_default_modulation_mode()
|
||||
|
||||
@@ -417,8 +417,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 =
|
||||
m_td_adjustment_enabled && zone.top_surface_contoning_surface_scatter_enabled ? CONTONING_SURFACE_SCATTER : 0.f;
|
||||
m_surface_scatter = zone.effective_top_surface_contoning_surface_scatter_enabled() ? CONTONING_SURFACE_SCATTER : 0.f;
|
||||
|
||||
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();
|
||||
@@ -450,6 +449,7 @@ TextureMappingContoningSolver::candidates_for_depth(int stack_layers) const
|
||||
const int depth = std::clamp(stack_layers,
|
||||
TextureMappingZone::MinTopSurfaceContoningStackLayers,
|
||||
TextureMappingZone::MaxTopSurfaceContoningStackLayers);
|
||||
std::lock_guard<std::mutex> lock(*m_candidate_mutex);
|
||||
auto found = m_candidates_by_depth.find(depth);
|
||||
if (found != m_candidates_by_depth.end())
|
||||
return found->second;
|
||||
@@ -656,8 +656,9 @@ TextureMappingContoningStack TextureMappingContoningSolver::solve(const std::arr
|
||||
m_component_roles,
|
||||
m_beam_search_stack_expansion_enabled);
|
||||
}
|
||||
const std::vector<uint16_t> surface_to_deep =
|
||||
solve_color_solver_ordered_stack_for_target(*ordered_candidates, target_rgb, ColorSolverMode::OklabSoftCap4Dark4);
|
||||
const ColorSolverOrderedStackResult solved =
|
||||
solve_color_solver_ordered_stack_result_for_target(*ordered_candidates, target_rgb, ColorSolverMode::OklabSoftCap4Dark4);
|
||||
const std::vector<uint16_t> &surface_to_deep = solved.surface_to_deep;
|
||||
if (!surface_to_deep.empty()) {
|
||||
out.bottom_to_top.reserve(surface_to_deep.size());
|
||||
auto append_component = [this, &out](uint16_t component_idx) {
|
||||
@@ -671,8 +672,11 @@ TextureMappingContoningStack TextureMappingContoningSolver::solve(const std::arr
|
||||
for (auto it = surface_to_deep.rbegin(); it != surface_to_deep.rend(); ++it)
|
||||
append_component(*it);
|
||||
}
|
||||
if (!out.bottom_to_top.empty())
|
||||
if (!out.bottom_to_top.empty()) {
|
||||
if (solved.has_rgb)
|
||||
out.rgb = solved.rgb;
|
||||
return out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ class PrintConfig;
|
||||
|
||||
struct TextureMappingContoningStack {
|
||||
std::vector<unsigned int> bottom_to_top;
|
||||
std::optional<std::array<float, 3>> rgb;
|
||||
};
|
||||
|
||||
class TextureMappingContoningSolver
|
||||
@@ -73,6 +74,7 @@ private:
|
||||
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;
|
||||
mutable std::shared_ptr<std::mutex> m_candidate_mutex { std::make_shared<std::mutex>() };
|
||||
mutable std::shared_ptr<ColorSolverOrderedStackCandidateCache> m_ordered_candidate_cache { std::make_shared<ColorSolverOrderedStackCandidateCache>() };
|
||||
mutable std::shared_ptr<std::mutex> m_ordered_candidate_cache_mutex { std::make_shared<std::mutex>() };
|
||||
};
|
||||
|
||||
@@ -2773,8 +2773,7 @@ std::optional<TexturePreviewSimulationSettings> texture_preview_simulation_setti
|
||||
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 ?
|
||||
zone->effective_top_surface_contoning_surface_scatter_enabled() ?
|
||||
k_contoning_preview_surface_scatter :
|
||||
0.f;
|
||||
}
|
||||
@@ -5798,7 +5797,7 @@ static size_t texture_preview_settings_signature_impl(size_t num_physical,
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_pattern_filaments));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_color_lower_surfaces ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_td_adjustment_enabled ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_surface_scatter_enabled ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.effective_top_surface_contoning_surface_scatter_enabled() ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_beer_lambert_rgb_correction_enabled ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_td_effective_alpha_correction_enabled ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.effective_top_surface_contoning_beam_search_stack_expansion_enabled() ? 1 : 0));
|
||||
@@ -5955,7 +5954,7 @@ static void texture_preview_mix_zone_baked_model_settings(size_t &signature,
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_pattern_filaments));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_color_lower_surfaces ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_td_adjustment_enabled ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_surface_scatter_enabled ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.effective_top_surface_contoning_surface_scatter_enabled() ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_beer_lambert_rgb_correction_enabled ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.top_surface_contoning_td_effective_alpha_correction_enabled ? 1 : 0));
|
||||
signature_mix(std::hash<int>{}(zone.effective_top_surface_contoning_beam_search_stack_expansion_enabled() ? 1 : 0));
|
||||
|
||||
@@ -2852,7 +2852,11 @@ public:
|
||||
gap / 2);
|
||||
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(top_surface_contoning_surface_scatter_enabled);
|
||||
m_top_surface_contoning_surface_scatter_checkbox->SetValue(
|
||||
TextureMappingZone::effective_top_surface_contoning_surface_scatter_enabled(
|
||||
top_surface_contoning_td_adjustment_enabled,
|
||||
top_surface_contoning_surface_scatter_enabled,
|
||||
top_surface_contoning_td_effective_alpha_correction_enabled));
|
||||
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,
|
||||
@@ -3628,9 +3632,12 @@ public:
|
||||
}
|
||||
bool top_surface_contoning_surface_scatter_enabled() const
|
||||
{
|
||||
return m_top_surface_contoning_surface_scatter_checkbox == nullptr ?
|
||||
TextureMappingZone::DefaultTopSurfaceContoningSurfaceScatterEnabled :
|
||||
m_top_surface_contoning_surface_scatter_checkbox->GetValue();
|
||||
return TextureMappingZone::effective_top_surface_contoning_surface_scatter_enabled(
|
||||
top_surface_contoning_td_adjustment_enabled(),
|
||||
m_top_surface_contoning_surface_scatter_checkbox == nullptr ?
|
||||
TextureMappingZone::DefaultTopSurfaceContoningSurfaceScatterEnabled :
|
||||
m_top_surface_contoning_surface_scatter_checkbox->GetValue(),
|
||||
top_surface_contoning_td_effective_alpha_correction_enabled());
|
||||
}
|
||||
bool top_surface_contoning_beer_lambert_rgb_correction_enabled() const
|
||||
{
|
||||
@@ -4440,8 +4447,14 @@ private:
|
||||
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_surface_scatter_checkbox->Show(contoning);
|
||||
m_top_surface_contoning_surface_scatter_checkbox->Enable(td_adjustment);
|
||||
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 =
|
||||
|
||||
Reference in New Issue
Block a user