Improve scheduling. Use beam search only on combined regions. Add buffer distance when prime towers are clamped to edge
This commit is contained in:
@@ -2070,14 +2070,17 @@ public:
|
||||
|
||||
bool run_one() override
|
||||
{
|
||||
int depth = -1;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (m_error || m_next >= m_depths.size())
|
||||
return false;
|
||||
depth = m_depths[m_next++];
|
||||
++m_active;
|
||||
m_active.fetch_add(1, std::memory_order_acq_rel);
|
||||
if (m_has_error.load(std::memory_order_acquire)) {
|
||||
finish_active_call();
|
||||
return false;
|
||||
}
|
||||
const size_t work_idx = m_next.fetch_add(1, std::memory_order_acq_rel);
|
||||
if (work_idx >= m_depths.size()) {
|
||||
finish_active_call();
|
||||
return false;
|
||||
}
|
||||
const int depth = m_depths[work_idx];
|
||||
|
||||
std::vector<TopSurfaceImageContoningVectorRegion> regions;
|
||||
std::exception_ptr error;
|
||||
@@ -2088,19 +2091,10 @@ public:
|
||||
error = std::current_exception();
|
||||
}
|
||||
|
||||
int 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_depths.size()) && m_active == 0;
|
||||
m_done = m_done || done;
|
||||
}
|
||||
if (done)
|
||||
m_cv.notify_all();
|
||||
if (error)
|
||||
store_error(error);
|
||||
const int completed = int(m_completed.fetch_add(1, std::memory_order_acq_rel) + 1);
|
||||
finish_active_call();
|
||||
if (!error && m_progress)
|
||||
m_progress(completed);
|
||||
return true;
|
||||
@@ -2109,22 +2103,47 @@ public:
|
||||
void wait()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
m_cv.wait(lock, [this]() { return m_done; });
|
||||
m_cv.wait(lock, [this]() { return done(); });
|
||||
if (m_error)
|
||||
std::rethrow_exception(m_error);
|
||||
}
|
||||
|
||||
private:
|
||||
bool done() const
|
||||
{
|
||||
return (m_has_error.load(std::memory_order_acquire) ||
|
||||
m_next.load(std::memory_order_acquire) >= m_depths.size()) &&
|
||||
m_active.load(std::memory_order_acquire) == 0;
|
||||
}
|
||||
|
||||
void store_error(std::exception_ptr error)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (!m_error)
|
||||
m_error = error;
|
||||
}
|
||||
m_has_error.store(true, std::memory_order_release);
|
||||
m_cv.notify_all();
|
||||
}
|
||||
|
||||
void finish_active_call()
|
||||
{
|
||||
m_active.fetch_sub(1, std::memory_order_acq_rel);
|
||||
if (done())
|
||||
m_cv.notify_all();
|
||||
}
|
||||
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_cv;
|
||||
std::vector<int> m_depths;
|
||||
BuildFn m_build;
|
||||
StoreFn m_store;
|
||||
ProgressFn m_progress;
|
||||
size_t m_next { 0 };
|
||||
int m_active { 0 };
|
||||
int m_completed { 0 };
|
||||
bool m_done { false };
|
||||
std::atomic<size_t> m_next { 0 };
|
||||
std::atomic<int> m_active { 0 };
|
||||
std::atomic<int> m_completed { 0 };
|
||||
std::atomic<bool> m_has_error { false };
|
||||
std::exception_ptr m_error;
|
||||
};
|
||||
|
||||
@@ -2134,46 +2153,53 @@ public:
|
||||
using RunFn = std::function<void(size_t)>;
|
||||
using ProgressFn = std::function<void(size_t)>;
|
||||
|
||||
TopSurfaceImageContoningAnchoredIndexWork(size_t count, RunFn run, ProgressFn progress)
|
||||
TopSurfaceImageContoningAnchoredIndexWork(size_t count, RunFn run, ProgressFn progress, size_t chunk_size = 64)
|
||||
: m_count(count)
|
||||
, m_run(std::move(run))
|
||||
, m_progress(std::move(progress))
|
||||
, m_chunk_size(std::max<size_t>(1, chunk_size))
|
||||
{
|
||||
m_done = m_count == 0;
|
||||
}
|
||||
|
||||
size_t task_count() const
|
||||
{
|
||||
return (m_count + m_chunk_size - 1) / m_chunk_size;
|
||||
}
|
||||
|
||||
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;
|
||||
m_active.fetch_add(1, std::memory_order_acq_rel);
|
||||
if (m_has_error.load(std::memory_order_acquire)) {
|
||||
finish_active_call();
|
||||
return false;
|
||||
}
|
||||
const size_t begin = m_next.fetch_add(m_chunk_size, std::memory_order_acq_rel);
|
||||
if (begin >= m_count) {
|
||||
finish_active_call();
|
||||
return false;
|
||||
}
|
||||
const size_t end = std::min(begin + m_chunk_size, m_count);
|
||||
|
||||
std::exception_ptr error;
|
||||
size_t processed = 0;
|
||||
try {
|
||||
m_run(idx);
|
||||
for (size_t idx = begin; idx < end; ++idx) {
|
||||
if (m_has_error.load(std::memory_order_acquire))
|
||||
break;
|
||||
m_run(idx);
|
||||
++processed;
|
||||
}
|
||||
} 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)
|
||||
if (error)
|
||||
store_error(error);
|
||||
const size_t completed = processed == 0 ?
|
||||
m_completed.load(std::memory_order_acquire) :
|
||||
m_completed.fetch_add(processed, std::memory_order_acq_rel) + processed;
|
||||
finish_active_call();
|
||||
if (!error && processed > 0 && m_progress)
|
||||
m_progress(completed);
|
||||
return true;
|
||||
}
|
||||
@@ -2181,21 +2207,47 @@ public:
|
||||
void wait()
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
m_cv.wait(lock, [this]() { return m_done; });
|
||||
m_cv.wait(lock, [this]() { return done(); });
|
||||
if (m_error)
|
||||
std::rethrow_exception(m_error);
|
||||
}
|
||||
|
||||
private:
|
||||
bool done() const
|
||||
{
|
||||
return (m_has_error.load(std::memory_order_acquire) ||
|
||||
m_next.load(std::memory_order_acquire) >= m_count) &&
|
||||
m_active.load(std::memory_order_acquire) == 0;
|
||||
}
|
||||
|
||||
void store_error(std::exception_ptr error)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (!m_error)
|
||||
m_error = error;
|
||||
}
|
||||
m_has_error.store(true, std::memory_order_release);
|
||||
m_cv.notify_all();
|
||||
}
|
||||
|
||||
void finish_active_call()
|
||||
{
|
||||
m_active.fetch_sub(1, std::memory_order_acq_rel);
|
||||
if (done())
|
||||
m_cv.notify_all();
|
||||
}
|
||||
|
||||
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 };
|
||||
size_t m_chunk_size { 1 };
|
||||
std::atomic<size_t> m_next { 0 };
|
||||
std::atomic<int> m_active { 0 };
|
||||
std::atomic<size_t> m_completed { 0 };
|
||||
std::atomic<bool> m_has_error { false };
|
||||
std::exception_ptr m_error;
|
||||
};
|
||||
|
||||
@@ -2307,6 +2359,8 @@ struct TopSurfaceImageContoningStackPlanKey {
|
||||
bool variable_layer_height_compensation { false };
|
||||
bool beam_search_stack_expansion { false };
|
||||
int mix_model { TextureMappingZone::DefaultGenericSolverMixModel };
|
||||
int color_prediction_mode { TextureMappingZone::DefaultTopSurfaceContoningColorPredictionMode };
|
||||
std::string calibrated_stack_model_key;
|
||||
|
||||
bool operator<(const TopSurfaceImageContoningStackPlanKey &rhs) const
|
||||
{
|
||||
@@ -2343,7 +2397,9 @@ struct TopSurfaceImageContoningStackPlanKey {
|
||||
td_effective_alpha_correction,
|
||||
variable_layer_height_compensation,
|
||||
beam_search_stack_expansion,
|
||||
mix_model) <
|
||||
mix_model,
|
||||
color_prediction_mode,
|
||||
calibrated_stack_model_key) <
|
||||
std::tie(rhs.source_layer,
|
||||
rhs.source_layer_id,
|
||||
rhs.target_layer,
|
||||
@@ -2377,7 +2433,9 @@ struct TopSurfaceImageContoningStackPlanKey {
|
||||
rhs.td_effective_alpha_correction,
|
||||
rhs.variable_layer_height_compensation,
|
||||
rhs.beam_search_stack_expansion,
|
||||
rhs.mix_model);
|
||||
rhs.mix_model,
|
||||
rhs.color_prediction_mode,
|
||||
rhs.calibrated_stack_model_key);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4606,6 +4664,31 @@ static std::optional<TopSurfaceImageContoningSolvedLabel> top_surface_image_cont
|
||||
label_by_stack);
|
||||
}
|
||||
|
||||
static std::optional<TopSurfaceImageContoningSolvedLabel> top_surface_image_contoning_solve_provisional_label(
|
||||
const std::array<float, 3> &rgb,
|
||||
int solve_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)
|
||||
{
|
||||
const int visible_layers = solve_layers;
|
||||
TextureMappingContoningStack stack =
|
||||
solver.solve_without_beam_search_stack_expansion(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(
|
||||
std::vector<int> &grid,
|
||||
int cols,
|
||||
@@ -4926,11 +5009,12 @@ 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,
|
||||
source_context.surface_to_deep_layer_heights_mm);
|
||||
cell_stacks[grid_idx] =
|
||||
solver.solve_without_beam_search_stack_expansion(sample->rgb,
|
||||
sample->solve_layers,
|
||||
lower_surface,
|
||||
sample->solve_layers,
|
||||
source_context.surface_to_deep_layer_heights_mm);
|
||||
if (debug_stride > 0 &&
|
||||
row % debug_stride == 0 &&
|
||||
col % debug_stride == 0) {
|
||||
@@ -4969,7 +5053,7 @@ static void top_surface_image_contoning_solve_anchored_region(
|
||||
if (build_state != nullptr)
|
||||
build_state->set_work(sample_work);
|
||||
try {
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, grid_cells, 32),
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, sample_work->task_count(), 1),
|
||||
[&](const tbb::blocked_range<size_t> &range) {
|
||||
for (size_t idx = range.begin(); idx != range.end(); ++idx)
|
||||
sample_work->run_one();
|
||||
@@ -4990,7 +5074,7 @@ static void top_surface_image_contoning_solve_anchored_region(
|
||||
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);
|
||||
label_cell(row, col, cell_stacks[grid_idx], cell_samples[grid_idx]->solve_layers);
|
||||
}
|
||||
}
|
||||
if (debug_enabled) {
|
||||
@@ -5542,6 +5626,8 @@ static TopSurfaceImageContoningStackPlanKey top_surface_image_contoning_anchored
|
||||
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;
|
||||
key.color_prediction_mode = zone.effective_top_surface_contoning_color_prediction_mode();
|
||||
key.calibrated_stack_model_key = solver.calibrated_stack_model_key();
|
||||
return key;
|
||||
}
|
||||
|
||||
@@ -5667,17 +5753,16 @@ static std::vector<TopSurfaceImageContoningVectorRegion> top_surface_image_conto
|
||||
std::vector<TopSurfaceImageContoningVectorLabel> labels;
|
||||
std::map<std::pair<std::vector<unsigned int>, int>, int> label_by_stack;
|
||||
|
||||
auto solve_cell = [&](int row, int col, const std::array<float, 3> &target_rgb, int solve_layers, int available_depth) {
|
||||
auto solve_cell = [&](int row, int col, const std::array<float, 3> &target_rgb, int solve_layers, int) {
|
||||
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,
|
||||
source->surface_to_deep_layer_heights_mm,
|
||||
labels,
|
||||
label_by_stack);
|
||||
top_surface_image_contoning_solve_provisional_label(target_rgb,
|
||||
solve_layers,
|
||||
solver,
|
||||
source_surface == TopSurfaceImageSourceSurface::Bottom &&
|
||||
plan.contoning_td_adjustment_enabled,
|
||||
source->surface_to_deep_layer_heights_mm,
|
||||
labels,
|
||||
label_by_stack);
|
||||
if (!solved)
|
||||
return std::optional<TopSurfaceImageContoningSolvedLabel>();
|
||||
grid[size_t(row * cols + col)] = solved->label;
|
||||
@@ -5884,15 +5969,14 @@ static std::shared_ptr<const TopSurfaceImageContoningStackPlan> top_surface_imag
|
||||
|
||||
auto solve_cell = [&](int row, int col, const std::array<float, 3> &target_rgb, int solve_layers, 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,
|
||||
source_context->surface_to_deep_layer_heights_mm,
|
||||
out->labels,
|
||||
label_by_stack);
|
||||
top_surface_image_contoning_solve_provisional_label(target_rgb,
|
||||
solve_layers,
|
||||
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)
|
||||
return std::optional<TopSurfaceImageContoningSolvedLabel>();
|
||||
TopSurfaceImageContoningStackPlanCell &cell = out->cells[size_t(row * cols + col)];
|
||||
@@ -6088,6 +6172,8 @@ static TopSurfaceImageContoningStackPlanKey top_surface_image_contoning_stack_pl
|
||||
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;
|
||||
key.color_prediction_mode = zone.effective_top_surface_contoning_color_prediction_mode();
|
||||
key.calibrated_stack_model_key = solver.calibrated_stack_model_key();
|
||||
return key;
|
||||
}
|
||||
|
||||
@@ -9826,6 +9912,41 @@ void export_group_fills_to_svg(const char *path, const std::vector<SurfaceFill>
|
||||
#endif
|
||||
|
||||
// friend to Layer
|
||||
void Layer::prebuild_contoning_stack_plan_cache(std::function<void()> throw_if_canceled,
|
||||
TopSurfaceImageContoningStackPlanCache *contoning_stack_plan_cache) const
|
||||
{
|
||||
if (contoning_stack_plan_cache == nullptr)
|
||||
return;
|
||||
const ThrowIfCanceled *throw_if_canceled_ptr = throw_if_canceled ? &throw_if_canceled : nullptr;
|
||||
check_canceled(throw_if_canceled_ptr);
|
||||
const PrintObject *object = this->object();
|
||||
if (object == nullptr || object->print() == nullptr)
|
||||
return;
|
||||
const TextureMappingManager &texture_mgr = object->print()->texture_mapping_manager();
|
||||
bool has_surface_anchored_contoning = false;
|
||||
for (const LayerRegion *layerm : m_regions) {
|
||||
check_canceled(throw_if_canceled_ptr);
|
||||
if (layerm == nullptr)
|
||||
continue;
|
||||
const int raw_zone_id = layerm->region().config().solid_infill_filament.value;
|
||||
if (raw_zone_id <= 0)
|
||||
continue;
|
||||
const TextureMappingZone *zone = texture_mgr.zone_from_id(unsigned(raw_zone_id));
|
||||
if (zone != nullptr &&
|
||||
zone->enabled &&
|
||||
!zone->deleted &&
|
||||
zone->top_surface_image_printing_active() &&
|
||||
zone->top_surface_contoning_active() &&
|
||||
zone->effective_top_surface_contoning_surface_anchored_stacks_enabled()) {
|
||||
has_surface_anchored_contoning = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_surface_anchored_contoning)
|
||||
return;
|
||||
top_surface_image_region_plans(*this, contoning_stack_plan_cache, throw_if_canceled_ptr);
|
||||
}
|
||||
|
||||
void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree,
|
||||
FillAdaptive::Octree* support_fill_octree,
|
||||
FillLightning::Generator* lightning_generator,
|
||||
|
||||
@@ -204,6 +204,8 @@ public:
|
||||
FillLightning::Generator* lightning_generator = nullptr,
|
||||
std::function<void()> throw_if_canceled = {},
|
||||
TopSurfaceImageContoningStackPlanCache *contoning_stack_plan_cache = nullptr);
|
||||
void prebuild_contoning_stack_plan_cache(std::function<void()> throw_if_canceled,
|
||||
TopSurfaceImageContoningStackPlanCache *contoning_stack_plan_cache) const;
|
||||
Polylines generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Octree *adaptive_fill_octree,
|
||||
FillAdaptive::Octree *support_fill_octree,
|
||||
FillLightning::Generator* lightning_generator) const;
|
||||
|
||||
@@ -992,6 +992,23 @@ void PrintObject::infill()
|
||||
const auto& support_fill_octree = this->m_adaptive_fill_octrees.second;
|
||||
const std::function<void()> throw_if_canceled = [print]() { print->throw_if_canceled(); };
|
||||
auto contoning_stack_plan_cache = make_top_surface_image_contoning_stack_plan_cache();
|
||||
const bool prebuild_contoning_stack_plans =
|
||||
std::any_of(print->texture_mapping_manager().zones().begin(),
|
||||
print->texture_mapping_manager().zones().end(),
|
||||
[](const TextureMappingZone &zone) {
|
||||
return zone.enabled &&
|
||||
!zone.deleted &&
|
||||
zone.top_surface_image_printing_active() &&
|
||||
zone.top_surface_contoning_active() &&
|
||||
zone.effective_top_surface_contoning_surface_anchored_stacks_enabled();
|
||||
});
|
||||
if (prebuild_contoning_stack_plans) {
|
||||
for (Layer *layer : m_layers) {
|
||||
print->throw_if_canceled();
|
||||
layer->prebuild_contoning_stack_plan_cache(throw_if_canceled, contoning_stack_plan_cache.get());
|
||||
}
|
||||
m_print->throw_if_canceled();
|
||||
}
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - start";
|
||||
tbb::parallel_for(
|
||||
|
||||
@@ -672,6 +672,37 @@ TextureMappingContoningStack TextureMappingContoningSolver::solve(const std::arr
|
||||
bool lower_surface,
|
||||
int visible_stack_layers,
|
||||
const std::vector<float> &surface_to_deep_layer_heights_mm) const
|
||||
{
|
||||
return solve_impl(target_rgb,
|
||||
stack_layers,
|
||||
lower_surface,
|
||||
visible_stack_layers,
|
||||
surface_to_deep_layer_heights_mm,
|
||||
m_beam_search_stack_expansion_enabled);
|
||||
}
|
||||
|
||||
TextureMappingContoningStack TextureMappingContoningSolver::solve_without_beam_search_stack_expansion(
|
||||
const std::array<float, 3> &target_rgb,
|
||||
int stack_layers,
|
||||
bool lower_surface,
|
||||
int visible_stack_layers,
|
||||
const std::vector<float> &surface_to_deep_layer_heights_mm) const
|
||||
{
|
||||
return solve_impl(target_rgb,
|
||||
stack_layers,
|
||||
lower_surface,
|
||||
visible_stack_layers,
|
||||
surface_to_deep_layer_heights_mm,
|
||||
false);
|
||||
}
|
||||
|
||||
TextureMappingContoningStack TextureMappingContoningSolver::solve_impl(
|
||||
const std::array<float, 3> &target_rgb,
|
||||
int stack_layers,
|
||||
bool lower_surface,
|
||||
int visible_stack_layers,
|
||||
const std::vector<float> &surface_to_deep_layer_heights_mm,
|
||||
bool beam_search_stack_expansion_enabled) const
|
||||
{
|
||||
TextureMappingContoningStack out;
|
||||
if (!valid())
|
||||
@@ -706,7 +737,7 @@ 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,
|
||||
beam_search_stack_expansion_enabled,
|
||||
depth_layer_opacities,
|
||||
m_calibrated_stack_model.valid() ? &m_calibrated_stack_model : nullptr);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Slic3r {
|
||||
@@ -35,12 +36,19 @@ public:
|
||||
bool valid() const { return !m_component_ids.empty() && m_component_ids.size() == m_component_colors.size(); }
|
||||
const std::vector<unsigned int>& component_ids() const { return m_component_ids; }
|
||||
const std::vector<unsigned int>& components_bottom_to_top() const { return m_components_bottom_to_top; }
|
||||
std::string calibrated_stack_model_key() const { return m_calibrated_stack_model.valid() ? m_calibrated_stack_model.cache_key() : std::string(); }
|
||||
|
||||
TextureMappingContoningStack solve(const std::array<float, 3> &target_rgb,
|
||||
int stack_layers,
|
||||
bool lower_surface = false,
|
||||
int visible_stack_layers = 0,
|
||||
const std::vector<float> &surface_to_deep_layer_heights_mm = {}) const;
|
||||
TextureMappingContoningStack solve_without_beam_search_stack_expansion(
|
||||
const std::array<float, 3> &target_rgb,
|
||||
int stack_layers,
|
||||
bool lower_surface = false,
|
||||
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,
|
||||
@@ -61,6 +69,12 @@ private:
|
||||
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;
|
||||
TextureMappingContoningStack solve_impl(const std::array<float, 3> &target_rgb,
|
||||
int stack_layers,
|
||||
bool lower_surface,
|
||||
int visible_stack_layers,
|
||||
const std::vector<float> &surface_to_deep_layer_heights_mm,
|
||||
bool beam_search_stack_expansion_enabled) const;
|
||||
|
||||
std::vector<unsigned int> m_component_ids;
|
||||
std::vector<unsigned int> m_components_bottom_to_top;
|
||||
|
||||
@@ -90,6 +90,7 @@ extern wxPopupWindow* wxCurrentPopupWindow;
|
||||
#endif
|
||||
|
||||
static constexpr const float TRACKBALLSIZE = 0.8f;
|
||||
static constexpr float WIPE_TOWER_EDGE_BUFFER = 20.f;
|
||||
|
||||
static Slic3r::ColorRGBA DEFAULT_BG_LIGHT_COLOR = { 0.906f, 0.906f, 0.906f, 1.0f };
|
||||
static Slic3r::ColorRGBA DEFAULT_BG_LIGHT_COLOR_DARK = { 0.329f, 0.329f, 0.353f, 1.0f };
|
||||
@@ -2877,7 +2878,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
const float texture_z_max = float(wipe_tower_size(2));
|
||||
|
||||
{
|
||||
const float margin = WIPE_TOWER_MARGIN + brim_width;
|
||||
const float margin = WIPE_TOWER_MARGIN + brim_width + WIPE_TOWER_EDGE_BUFFER;
|
||||
BoundingBoxf3 plate_bbox = part_plate->get_bounding_box();
|
||||
BoundingBoxf plate_bbox_2d(Vec2d(plate_bbox.min(0), plate_bbox.min(1)), Vec2d(plate_bbox.max(0), plate_bbox.max(1)));
|
||||
const std::vector<Pointfs> &extruder_areas = part_plate->get_extruder_areas();
|
||||
|
||||
@@ -43,6 +43,8 @@ constexpr size_t k_simulated_texture_preview_max_pixels = 2048ull * 2048ull;
|
||||
constexpr unsigned int k_temporary_simulated_texture_preview_max_edge = 1024;
|
||||
constexpr size_t k_temporary_simulated_texture_preview_max_pixels = 1024ull * 1024ull;
|
||||
constexpr size_t k_temporary_simulated_texture_preview_min_source_pixels = k_temporary_simulated_texture_preview_max_pixels * 3 / 2;
|
||||
constexpr unsigned int k_temporary_contoning_flat_surface_preview_max_edge = 384;
|
||||
constexpr size_t k_temporary_contoning_flat_surface_preview_max_pixels = 384ull * 384ull;
|
||||
constexpr size_t k_surface_gradient_preview_max_components = 10;
|
||||
constexpr size_t k_surface_gradient_preview_lut_size = 33;
|
||||
constexpr size_t k_contoning_flat_surface_preview_max_candidates = 250000;
|
||||
@@ -99,6 +101,7 @@ struct TexturePreviewSimulationSettings
|
||||
bool contoning_flat_surface_beer_lambert_rgb_correction = false;
|
||||
bool contoning_flat_surface_td_effective_alpha_correction = false;
|
||||
bool contoning_flat_surface_beam_search_stack_expansion = false;
|
||||
bool contoning_flat_surface_force_low_resolution = false;
|
||||
int contoning_flat_surface_pattern_filaments = TextureMappingZone::DefaultTopSurfaceContoningPatternFilaments;
|
||||
bool simulate_top_surface_lod = false;
|
||||
float top_surface_lod_pitch_mm = 0.f;
|
||||
@@ -176,6 +179,12 @@ struct TexturePreviewSimulationCacheEntry
|
||||
std::shared_ptr<TexturePreviewSimulationJobState> pending_job_state;
|
||||
};
|
||||
|
||||
struct TexturePreviewSizeLimit
|
||||
{
|
||||
unsigned int max_edge { k_simulated_texture_preview_max_edge };
|
||||
size_t max_pixels { k_simulated_texture_preview_max_pixels };
|
||||
};
|
||||
|
||||
struct TexturePreviewVertexColorSimulationResult
|
||||
{
|
||||
size_t signature { 0 };
|
||||
@@ -891,6 +900,16 @@ std::array<unsigned int, 2> simulated_texture_preview_size(unsigned int width,
|
||||
limited_simulated_texture_preview_size(width, height) :
|
||||
std::array<unsigned int, 2>{ width, height };
|
||||
|
||||
if (settings.contoning_flat_surface_force_low_resolution) {
|
||||
const std::array<unsigned int, 2> low_size =
|
||||
limited_simulated_texture_preview_size(width,
|
||||
height,
|
||||
k_temporary_contoning_flat_surface_preview_max_edge,
|
||||
k_temporary_contoning_flat_surface_preview_max_pixels);
|
||||
size[0] = std::min(size[0], low_size[0]);
|
||||
size[1] = std::min(size[1], low_size[1]);
|
||||
}
|
||||
|
||||
if (settings.contoning_flat_surface_quantization &&
|
||||
settings.simulate_top_surface_lod &&
|
||||
std::isfinite(settings.texture_preview_mm_per_pixel) &&
|
||||
@@ -922,26 +941,52 @@ bool simulated_texture_preview_needs_temporary_result(unsigned int width,
|
||||
unsigned int height,
|
||||
const TexturePreviewSimulationSettings &settings)
|
||||
{
|
||||
auto final_and_temporary_pixels = [&settings, width, height]() {
|
||||
const std::array<unsigned int, 2> final_size = simulated_texture_preview_size(width, height, settings);
|
||||
const TexturePreviewSizeLimit temporary_limit =
|
||||
settings.contoning_flat_surface_quantization ?
|
||||
TexturePreviewSizeLimit{ k_temporary_contoning_flat_surface_preview_max_edge,
|
||||
k_temporary_contoning_flat_surface_preview_max_pixels } :
|
||||
TexturePreviewSizeLimit{ k_temporary_simulated_texture_preview_max_edge,
|
||||
k_temporary_simulated_texture_preview_max_pixels };
|
||||
const std::array<unsigned int, 2> temporary_size =
|
||||
simulated_texture_preview_size(width,
|
||||
height,
|
||||
settings,
|
||||
temporary_limit.max_edge,
|
||||
temporary_limit.max_pixels);
|
||||
return std::array<size_t, 2>{
|
||||
size_t(final_size[0]) * size_t(final_size[1]),
|
||||
size_t(temporary_size[0]) * size_t(temporary_size[1])
|
||||
};
|
||||
};
|
||||
|
||||
if (settings.contoning_flat_surface_quantization) {
|
||||
const std::array<size_t, 2> pixels = final_and_temporary_pixels();
|
||||
return pixels[0] > pixels[1] && pixels[0] > pixels[1] * 5 / 4;
|
||||
}
|
||||
|
||||
const size_t source_pixels = size_t(width) * size_t(height);
|
||||
if (source_pixels <= k_temporary_simulated_texture_preview_min_source_pixels)
|
||||
return false;
|
||||
|
||||
const std::array<unsigned int, 2> final_size = simulated_texture_preview_size(width, height, settings);
|
||||
const std::array<unsigned int, 2> temporary_size =
|
||||
simulated_texture_preview_size(width,
|
||||
height,
|
||||
settings,
|
||||
k_temporary_simulated_texture_preview_max_edge,
|
||||
k_temporary_simulated_texture_preview_max_pixels);
|
||||
return size_t(final_size[0]) * size_t(final_size[1]) > size_t(temporary_size[0]) * size_t(temporary_size[1]);
|
||||
const std::array<size_t, 2> pixels = final_and_temporary_pixels();
|
||||
return pixels[0] > pixels[1];
|
||||
}
|
||||
|
||||
size_t temporary_simulated_texture_preview_signature(size_t signature)
|
||||
TexturePreviewSizeLimit temporary_simulated_texture_preview_size_limit(const TexturePreviewSimulationSettings &settings)
|
||||
{
|
||||
if (settings.contoning_flat_surface_quantization)
|
||||
return { k_temporary_contoning_flat_surface_preview_max_edge, k_temporary_contoning_flat_surface_preview_max_pixels };
|
||||
return { k_temporary_simulated_texture_preview_max_edge, k_temporary_simulated_texture_preview_max_pixels };
|
||||
}
|
||||
|
||||
size_t temporary_simulated_texture_preview_signature(size_t signature, const TexturePreviewSizeLimit &limit)
|
||||
{
|
||||
signature ^= 0x4a7c15f17e315123ull + (signature << 6) + (signature >> 2);
|
||||
signature ^= std::hash<unsigned int>{}(k_temporary_simulated_texture_preview_max_edge) + 0x9e3779b97f4a7c15ull +
|
||||
signature ^= std::hash<unsigned int>{}(limit.max_edge) + 0x9e3779b97f4a7c15ull +
|
||||
(signature << 6) + (signature >> 2);
|
||||
signature ^= std::hash<size_t>{}(k_temporary_simulated_texture_preview_max_pixels) + 0x9e3779b97f4a7c15ull +
|
||||
signature ^= std::hash<size_t>{}(limit.max_pixels) + 0x9e3779b97f4a7c15ull +
|
||||
(signature << 6) + (signature >> 2);
|
||||
return signature;
|
||||
}
|
||||
@@ -2782,6 +2827,8 @@ std::optional<TexturePreviewSimulationSettings> texture_preview_simulation_setti
|
||||
const int effective_color_prediction_mode =
|
||||
TextureMappingZone::effective_top_surface_contoning_color_prediction_mode(
|
||||
zone->top_surface_contoning_color_prediction_mode);
|
||||
const bool calibrated_color_prediction =
|
||||
TextureMappingZone::top_surface_contoning_color_prediction_mode_is_calibrated(effective_color_prediction_mode);
|
||||
settings.contoning_flat_surface_beer_lambert_rgb_correction =
|
||||
settings.contoning_flat_surface_td_adjustment &&
|
||||
effective_color_prediction_mode == int(TextureMappingZone::ContoningColorPredictionBeerLambertRgb);
|
||||
@@ -2791,6 +2838,8 @@ std::optional<TexturePreviewSimulationSettings> texture_preview_simulation_setti
|
||||
effective_color_prediction_mode == int(TextureMappingZone::ContoningColorPredictionCalibratedCurrentLinearAffine));
|
||||
settings.contoning_flat_surface_beam_search_stack_expansion =
|
||||
zone->effective_top_surface_contoning_beam_search_stack_expansion_enabled();
|
||||
settings.contoning_flat_surface_force_low_resolution =
|
||||
settings.contoning_flat_surface_td_adjustment && calibrated_color_prediction;
|
||||
settings.contoning_flat_surface_surface_scatter =
|
||||
zone->effective_top_surface_contoning_surface_scatter_enabled() ?
|
||||
k_contoning_preview_surface_scatter :
|
||||
@@ -2908,6 +2957,7 @@ size_t texture_preview_simulation_signature(const ModelVolume &model_volume,
|
||||
mix(std::hash<int>{}(settings.contoning_flat_surface_beer_lambert_rgb_correction ? 1 : 0));
|
||||
mix(std::hash<int>{}(settings.contoning_flat_surface_td_effective_alpha_correction ? 1 : 0));
|
||||
mix(std::hash<int>{}(settings.contoning_flat_surface_beam_search_stack_expansion ? 1 : 0));
|
||||
mix(std::hash<int>{}(settings.contoning_flat_surface_force_low_resolution ? 1 : 0));
|
||||
if (settings.contoning_flat_surface_quantization) {
|
||||
mix(std::hash<int>{}(settings.contoning_flat_surface_pattern_filaments));
|
||||
mix(std::hash<int>{}(settings.simulate_top_surface_lod ? 1 : 0));
|
||||
@@ -3732,8 +3782,9 @@ const GUI::GLTexture *simulated_texture_preview_texture_for_filament(const Model
|
||||
const unsigned int width = model_volume.imported_texture_width;
|
||||
const unsigned int height = model_volume.imported_texture_height;
|
||||
const bool needs_temporary_result = simulated_texture_preview_needs_temporary_result(width, height, *settings);
|
||||
const TexturePreviewSizeLimit temporary_size_limit = temporary_simulated_texture_preview_size_limit(*settings);
|
||||
const size_t temporary_signature = needs_temporary_result ?
|
||||
temporary_simulated_texture_preview_signature(simulation_signature) :
|
||||
temporary_simulated_texture_preview_signature(simulation_signature, temporary_size_limit) :
|
||||
size_t(0);
|
||||
|
||||
consume_temporary_simulated_texture_preview_result(entry);
|
||||
@@ -3783,10 +3834,9 @@ const GUI::GLTexture *simulated_texture_preview_texture_for_filament(const Model
|
||||
source_raw_component_channels = std::move(source_raw_component_channels),
|
||||
background_color,
|
||||
job_state,
|
||||
temporary_size_limit,
|
||||
simulation_settings = std::move(simulation_settings)]() mutable {
|
||||
if (temporary_signature != 0 && job_state != nullptr) {
|
||||
const unsigned int temp_edge = k_temporary_simulated_texture_preview_max_edge;
|
||||
const size_t temp_pixels = k_temporary_simulated_texture_preview_max_pixels;
|
||||
TexturePreviewSimulationResult temporary_result =
|
||||
build_simulated_texture_preview_result(temporary_signature,
|
||||
width,
|
||||
@@ -3797,8 +3847,8 @@ const GUI::GLTexture *simulated_texture_preview_texture_for_filament(const Model
|
||||
source_raw_component_channels,
|
||||
background_color,
|
||||
simulation_settings,
|
||||
temp_edge,
|
||||
temp_pixels);
|
||||
temporary_size_limit.max_edge,
|
||||
temporary_size_limit.max_pixels);
|
||||
std::lock_guard<std::mutex> lock(job_state->mutex);
|
||||
job_state->temporary_result = std::move(temporary_result);
|
||||
}
|
||||
@@ -5837,6 +5887,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.effective_top_surface_contoning_color_prediction_mode()));
|
||||
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));
|
||||
@@ -5994,6 +6045,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.effective_top_surface_contoning_color_prediction_mode()));
|
||||
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));
|
||||
@@ -6186,7 +6238,7 @@ void render_model_texture_preview_models(
|
||||
|
||||
const bool force_original_texture =
|
||||
color_match_active || texture_preview_halftone_simulation_enabled_for_filament(filament_ids[idx], num_physical, texture_mgr);
|
||||
const GUI::GLTexture *preview_texture = force_original_texture ?
|
||||
const GUI::GLTexture *base_preview_texture = force_original_texture ?
|
||||
&texture :
|
||||
simulated_texture_preview_texture_for_filament(model_volume,
|
||||
model_matrix,
|
||||
@@ -6195,15 +6247,9 @@ void render_model_texture_preview_models(
|
||||
texture_mgr,
|
||||
texture_signature,
|
||||
texture);
|
||||
if (preview_texture == nullptr || preview_texture->get_id() == 0)
|
||||
if (base_preview_texture == nullptr || base_preview_texture->get_id() == 0)
|
||||
continue;
|
||||
|
||||
if (preview_texture->get_id() != bound_texture_id) {
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, preview_texture->get_id()));
|
||||
bound_texture_id = preview_texture->get_id();
|
||||
}
|
||||
|
||||
bool contoning_flat_top_ready = false;
|
||||
bool contoning_flat_bottom_ready = false;
|
||||
bool contoning_flat_top_quantization = false;
|
||||
@@ -6256,6 +6302,20 @@ void render_model_texture_preview_models(
|
||||
contoning_flat_top_ready && contoning_flat_texture != nullptr && contoning_flat_texture->get_id() != 0;
|
||||
const bool contoning_flat_bottom_enabled =
|
||||
contoning_flat_bottom_ready && contoning_flat_bottom_texture != nullptr && contoning_flat_bottom_texture->get_id() != 0;
|
||||
const bool contoning_flat_pending =
|
||||
use_contoning_flat_texture &&
|
||||
((!contoning_flat_enabled && (contoning_flat_top_quantization || contoning_flat_top_pattern_blend)) ||
|
||||
(!contoning_flat_bottom_enabled && (contoning_flat_bottom_quantization || contoning_flat_bottom_pattern_blend)));
|
||||
const GUI::GLTexture *preview_texture = contoning_flat_pending ? &texture : base_preview_texture;
|
||||
if (preview_texture == nullptr || preview_texture->get_id() == 0)
|
||||
continue;
|
||||
|
||||
if (preview_texture->get_id() != bound_texture_id) {
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, preview_texture->get_id()));
|
||||
bound_texture_id = preview_texture->get_id();
|
||||
}
|
||||
|
||||
if (contoning_flat_enabled && contoning_flat_texture->get_id() != bound_contoning_flat_texture_id) {
|
||||
glsafe(::glActiveTexture(GL_TEXTURE1));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, contoning_flat_texture->get_id()));
|
||||
@@ -6324,7 +6384,7 @@ void render_model_texture_preview_model(
|
||||
const size_t texture_signature = model_volume_texture_preview_signature(model_volume);
|
||||
const bool force_original_texture =
|
||||
color_match_active || texture_preview_halftone_simulation_enabled_for_filament(filament_id, num_physical, texture_mgr);
|
||||
const GUI::GLTexture *preview_texture = force_original_texture ?
|
||||
const GUI::GLTexture *base_preview_texture = force_original_texture ?
|
||||
&texture :
|
||||
simulated_texture_preview_texture_for_filament(model_volume,
|
||||
model_matrix,
|
||||
@@ -6333,7 +6393,7 @@ void render_model_texture_preview_model(
|
||||
texture_mgr,
|
||||
texture_signature,
|
||||
texture);
|
||||
if (preview_texture == nullptr || preview_texture->get_id() == 0)
|
||||
if (base_preview_texture == nullptr || base_preview_texture->get_id() == 0)
|
||||
return;
|
||||
|
||||
const TexturePreviewRenderState render_state = begin_render_state(opaque);
|
||||
@@ -6349,8 +6409,6 @@ void render_model_texture_preview_model(
|
||||
print_volume_z);
|
||||
set_color_match_preview_uniforms(*shader, color_match);
|
||||
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, preview_texture->get_id()));
|
||||
shader->set_uniform("uniform_texture", 0);
|
||||
shader->set_uniform("contoning_flat_surface_texture", 1);
|
||||
shader->set_uniform("contoning_flat_surface_bottom_texture", 2);
|
||||
@@ -6406,6 +6464,19 @@ void render_model_texture_preview_model(
|
||||
contoning_flat_top_ready && contoning_flat_texture != nullptr && contoning_flat_texture->get_id() != 0;
|
||||
const bool contoning_flat_bottom_enabled =
|
||||
contoning_flat_bottom_ready && contoning_flat_bottom_texture != nullptr && contoning_flat_bottom_texture->get_id() != 0;
|
||||
const bool contoning_flat_pending =
|
||||
use_contoning_flat_texture &&
|
||||
((!contoning_flat_enabled && (contoning_flat_top_quantization || contoning_flat_top_pattern_blend)) ||
|
||||
(!contoning_flat_bottom_enabled && (contoning_flat_bottom_quantization || contoning_flat_bottom_pattern_blend)));
|
||||
const GUI::GLTexture *preview_texture = contoning_flat_pending ? &texture : base_preview_texture;
|
||||
if (preview_texture == nullptr || preview_texture->get_id() == 0) {
|
||||
shader->stop_using();
|
||||
restore_render_state(render_state);
|
||||
return;
|
||||
}
|
||||
|
||||
glsafe(::glActiveTexture(GL_TEXTURE0));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, preview_texture->get_id()));
|
||||
if (contoning_flat_enabled) {
|
||||
glsafe(::glActiveTexture(GL_TEXTURE1));
|
||||
glsafe(::glBindTexture(GL_TEXTURE_2D, contoning_flat_texture->get_id()));
|
||||
|
||||
@@ -64,6 +64,7 @@ static const int PARTPLATE_TEXT_OFFSET_X1 = 3;
|
||||
static const int PARTPLATE_TEXT_OFFSET_X2 = 1;
|
||||
static const int PARTPLATE_TEXT_OFFSET_Y = 1;
|
||||
static const int PARTPLATE_PLATENAME_OFFSET_Y = 10;
|
||||
static const float WIPE_TOWER_EDGE_BUFFER = 20.f;
|
||||
|
||||
const float WIPE_TOWER_DEFAULT_X_POS = 165.;
|
||||
const float WIPE_TOWER_DEFAULT_Y_POS = 250.; // Max y
|
||||
@@ -4443,7 +4444,7 @@ void PartPlateList::set_default_wipe_tower_pos_for_plate(int plate_idx, bool ini
|
||||
brim_width = brim_opt->value;
|
||||
if (brim_width < 0) brim_width = WipeTower::get_auto_brim_by_height((float) wipe_tower_size.z());
|
||||
}
|
||||
const float margin = WIPE_TOWER_MARGIN + brim_width;
|
||||
const float margin = WIPE_TOWER_MARGIN + brim_width + WIPE_TOWER_EDGE_BUFFER;
|
||||
|
||||
// clamp wipe tower position within plate boundaries
|
||||
{
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
#include "libslic3r/Polygon.hpp"
|
||||
#include "libslic3r/Print.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "libslic3r/GCode/WipeTower.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
@@ -242,6 +243,7 @@ wxDEFINE_EVENT(EVT_DEL_FILAMENT, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_ADD_CUSTOM_FILAMENT, ColorEvent);
|
||||
wxDEFINE_EVENT(EVT_NOTICE_CHILDE_SIZE_CHANGED, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_NOTICE_FULL_SCREEN_CHANGED, IntEvent);
|
||||
static constexpr float WIPE_TOWER_EDGE_BUFFER = 20.f;
|
||||
#define PRINTER_THUMBNAIL_SIZE (wxSize(40, 40)) // ORCA
|
||||
#define PRINTER_PANEL_SIZE ( wxSize(70, 60)) // ORCA
|
||||
#define PRINTER_PANEL_RADIUS (6) // ORCA
|
||||
@@ -378,6 +380,90 @@ static wxString temp_dir;
|
||||
|
||||
namespace {
|
||||
|
||||
static void clamp_wipe_tower_positions_for_slicing(PartPlateList &partplate_list, PresetBundle &preset_bundle)
|
||||
{
|
||||
DynamicPrintConfig &proj_cfg = preset_bundle.project_config;
|
||||
ConfigOptionFloats *wipe_tower_x = proj_cfg.option<ConfigOptionFloats>("wipe_tower_x", true);
|
||||
ConfigOptionFloats *wipe_tower_y = proj_cfg.option<ConfigOptionFloats>("wipe_tower_y", true);
|
||||
if (wipe_tower_x == nullptr || wipe_tower_y == nullptr || wipe_tower_x->values.empty() || wipe_tower_y->values.empty())
|
||||
return;
|
||||
|
||||
const DynamicPrintConfig &print_cfg = preset_bundle.prints.get_edited_preset().config;
|
||||
const ConfigOptionBool *enable_prime_tower = print_cfg.option<ConfigOptionBool>("enable_prime_tower");
|
||||
if (enable_prime_tower == nullptr || !enable_prime_tower->value)
|
||||
return;
|
||||
|
||||
wipe_tower_x->values.resize(partplate_list.get_plate_count(), wipe_tower_x->values.front());
|
||||
wipe_tower_y->values.resize(partplate_list.get_plate_count(), wipe_tower_y->values.front());
|
||||
|
||||
const ConfigOptionEnum<PrintSequence> *print_sequence = print_cfg.option<ConfigOptionEnum<PrintSequence>>("print_sequence");
|
||||
const ConfigOptionEnum<TimelapseType> *timelapse_type = print_cfg.option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
|
||||
const ConfigOptionBool *wrapping_opt = print_cfg.option<ConfigOptionBool>("enable_wrapping_detection");
|
||||
const bool need_wipe_tower = (timelapse_type != nullptr && timelapse_type->value == TimelapseType::tlSmooth) ||
|
||||
(wrapping_opt != nullptr && wrapping_opt->value);
|
||||
const float width = print_cfg.opt_float("prime_tower_width");
|
||||
const float prime_volume = print_cfg.opt_float("prime_volume");
|
||||
const int nozzle_nums = preset_bundle.get_printer_extruder_count();
|
||||
|
||||
for (int plate_id = 0; plate_id < partplate_list.get_plate_count(); ++plate_id) {
|
||||
PartPlate *part_plate = partplate_list.get_plate(plate_id);
|
||||
if (part_plate == nullptr || part_plate->get_objects_on_this_plate().empty())
|
||||
continue;
|
||||
if (part_plate->get_print_seq() == PrintSequence::ByObject ||
|
||||
(part_plate->get_print_seq() == PrintSequence::ByDefault && print_sequence != nullptr && print_sequence->value == PrintSequence::ByObject)) {
|
||||
if (part_plate->printable_instance_size() != 1)
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t texture_mapping_filaments_count = part_plate->estimate_wipe_tower_filaments_count(&proj_cfg);
|
||||
const size_t wipe_tower_filaments_count = need_wipe_tower ?
|
||||
std::max<size_t>(1, texture_mapping_filaments_count) :
|
||||
texture_mapping_filaments_count;
|
||||
if (!need_wipe_tower && wipe_tower_filaments_count < 2)
|
||||
continue;
|
||||
|
||||
Vec3d wipe_tower_size = part_plate->estimate_wipe_tower_size(print_cfg,
|
||||
width,
|
||||
prime_volume,
|
||||
nozzle_nums,
|
||||
int(wipe_tower_filaments_count),
|
||||
false,
|
||||
wrapping_opt != nullptr && wrapping_opt->value);
|
||||
if (wipe_tower_size(0) <= EPSILON || wipe_tower_size(1) <= EPSILON)
|
||||
continue;
|
||||
|
||||
float brim_width = print_cfg.opt_float("prime_tower_brim_width");
|
||||
if (brim_width < 0)
|
||||
brim_width = WipeTower::get_auto_brim_by_height((float) wipe_tower_size.z());
|
||||
const float margin = float(WIPE_TOWER_MARGIN) + brim_width + WIPE_TOWER_EDGE_BUFFER;
|
||||
|
||||
const Vec3d plate_origin = part_plate->get_origin();
|
||||
BoundingBoxf3 plate_bbox = part_plate->get_bounding_box();
|
||||
BoundingBoxf plate_bbox_2d(Vec2d(plate_bbox.min(0), plate_bbox.min(1)), Vec2d(plate_bbox.max(0), plate_bbox.max(1)));
|
||||
const std::vector<Pointfs> &extruder_areas = part_plate->get_extruder_areas();
|
||||
for (const Pointfs &points : extruder_areas) {
|
||||
BoundingBoxf bboxf(points);
|
||||
plate_bbox_2d.min = plate_bbox_2d.min(0) >= bboxf.min(0) ? plate_bbox_2d.min : bboxf.min;
|
||||
plate_bbox_2d.max = plate_bbox_2d.max(0) <= bboxf.max(0) ? plate_bbox_2d.max : bboxf.max;
|
||||
}
|
||||
|
||||
const coordf_t min_x = plate_bbox_2d.min(0) - plate_origin(0);
|
||||
const coordf_t max_x = plate_bbox_2d.max(0) - plate_origin(0);
|
||||
const coordf_t min_y = plate_bbox_2d.min(1) - plate_origin(1);
|
||||
const coordf_t max_y = plate_bbox_2d.max(1) - plate_origin(1);
|
||||
auto clamp_axis = [](float value, coordf_t min_value, coordf_t max_value, double size, float margin) {
|
||||
const float axis_min = float(min_value) + margin;
|
||||
const float axis_max = float(max_value) - margin - float(size);
|
||||
return axis_max < axis_min ? axis_min : std::min(std::max(value, axis_min), axis_max);
|
||||
};
|
||||
|
||||
ConfigOptionFloat x_opt(clamp_axis(wipe_tower_x->get_at(plate_id), min_x, max_x, wipe_tower_size(0), margin));
|
||||
ConfigOptionFloat y_opt(clamp_axis(wipe_tower_y->get_at(plate_id), min_y, max_y, wipe_tower_size(1), margin));
|
||||
wipe_tower_x->set_at(&x_opt, plate_id, 0);
|
||||
wipe_tower_y->set_at(&y_opt, plate_id, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static std::map<uint64_t, unsigned int> active_texture_zone_ids_by_stable_id_for_import(const TextureMappingManager &manager)
|
||||
{
|
||||
std::map<uint64_t, unsigned int> ids;
|
||||
@@ -14541,8 +14627,10 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
|
||||
this->preview->update_gcode_result(partplate_list.get_current_slice_result());
|
||||
}
|
||||
|
||||
if (PresetBundle *preset_bundle = wxGetApp().preset_bundle; preset_bundle != nullptr)
|
||||
if (PresetBundle *preset_bundle = wxGetApp().preset_bundle; preset_bundle != nullptr) {
|
||||
canonicalize_texture_mapping_config(*preset_bundle, true);
|
||||
clamp_wipe_tower_positions_for_slicing(this->partplate_list, *preset_bundle);
|
||||
}
|
||||
|
||||
background_process.fff_print()->set_check_multi_filaments_compatibility(wxGetApp().app_config->get("enable_high_low_temp_mixed_printing") == "false");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user