Preserve model textures and remap them to the new mesh when 'simplify model' is used
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -45,4 +45,6 @@ test.js
|
||||
.clangd
|
||||
internal_docs/
|
||||
*.flatpak
|
||||
/flatpak-repo/
|
||||
/flatpak-repo/
|
||||
*.3mf
|
||||
*.gcode
|
||||
|
||||
@@ -304,6 +304,8 @@ set(lisbslic3r_sources
|
||||
ModelArrange.hpp
|
||||
Model.cpp
|
||||
Model.hpp
|
||||
ModelTextureDataRemap.cpp
|
||||
ModelTextureDataRemap.hpp
|
||||
MTUtils.hpp
|
||||
MultiMaterialSegmentation.cpp
|
||||
MultiMaterialSegmentation.hpp
|
||||
|
||||
@@ -4580,11 +4580,23 @@ bool ColorFacetsAnnotation::set_from_triangle_sampler(const ModelVolume
|
||||
float split_color_threshold,
|
||||
const TextureMappingColorSubdivisionDepths &subdivision_depths,
|
||||
const std::vector<bool> *resample_triangles,
|
||||
const TextureMappingColorLeafResamplePredicate &resample_leaf)
|
||||
const TextureMappingColorLeafResamplePredicate &resample_leaf,
|
||||
const TextureMappingColorProgressFn &progress_fn)
|
||||
{
|
||||
return this->set_from_triangle_sampler(mv.mesh().its, sampler, max_depth, split_color_threshold, subdivision_depths, resample_triangles, resample_leaf, progress_fn);
|
||||
}
|
||||
|
||||
bool ColorFacetsAnnotation::set_from_triangle_sampler(const indexed_triangle_set &its,
|
||||
const TextureMappingColorSampler &sampler,
|
||||
int max_depth,
|
||||
float split_color_threshold,
|
||||
const TextureMappingColorSubdivisionDepths &subdivision_depths,
|
||||
const std::vector<bool> *resample_triangles,
|
||||
const TextureMappingColorLeafResamplePredicate &resample_leaf,
|
||||
const TextureMappingColorProgressFn &progress_fn)
|
||||
{
|
||||
TriangleColorSplittingData new_data;
|
||||
new_data.metadata_json = m_data.metadata_json;
|
||||
const indexed_triangle_set &its = mv.mesh().its;
|
||||
new_data.triangles_to_split.reserve(its.indices.size());
|
||||
if (resample_triangles != nullptr) {
|
||||
new_data.bitstream.reserve(m_data.bitstream.size());
|
||||
@@ -4600,6 +4612,21 @@ bool ColorFacetsAnnotation::set_from_triangle_sampler(const ModelVolume
|
||||
max_depth = std::clamp(max_depth, 0, 7);
|
||||
split_color_threshold = std::max(split_color_threshold, 0.f);
|
||||
|
||||
const size_t total_triangles = its.indices.size();
|
||||
int last_progress = -1;
|
||||
auto report_progress = [&progress_fn, total_triangles, &last_progress](size_t completed_triangles) {
|
||||
if (!progress_fn)
|
||||
return;
|
||||
const int progress = total_triangles == 0 ?
|
||||
100 :
|
||||
int((uint64_t(completed_triangles) * 100u) / uint64_t(total_triangles));
|
||||
if (progress != last_progress) {
|
||||
last_progress = progress;
|
||||
progress_fn(completed_triangles, total_triangles);
|
||||
}
|
||||
};
|
||||
report_progress(0);
|
||||
|
||||
size_t preserved_mapping_idx = 0;
|
||||
auto existing_triangle_range = [this, &preserved_mapping_idx](size_t tri_idx,
|
||||
int &bitstream_start,
|
||||
@@ -4655,13 +4682,20 @@ bool ColorFacetsAnnotation::set_from_triangle_sampler(const ModelVolume
|
||||
};
|
||||
|
||||
for (size_t tri_idx = 0; tri_idx < its.indices.size(); ++tri_idx) {
|
||||
auto report_triangle_done = [&report_progress, tri_idx]() {
|
||||
report_progress(tri_idx + 1);
|
||||
};
|
||||
const auto &tri = its.indices[tri_idx];
|
||||
if (tri[0] < 0 || tri[1] < 0 || tri[2] < 0)
|
||||
if (tri[0] < 0 || tri[1] < 0 || tri[2] < 0) {
|
||||
report_triangle_done();
|
||||
continue;
|
||||
}
|
||||
if (size_t(tri[0]) >= its.vertices.size() ||
|
||||
size_t(tri[1]) >= its.vertices.size() ||
|
||||
size_t(tri[2]) >= its.vertices.size())
|
||||
size_t(tri[2]) >= its.vertices.size()) {
|
||||
report_triangle_done();
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::array<Vec3f, 3> vertices = {
|
||||
its.vertices[size_t(tri[0])].cast<float>(),
|
||||
@@ -4676,8 +4710,10 @@ bool ColorFacetsAnnotation::set_from_triangle_sampler(const ModelVolume
|
||||
if (resample_triangles != nullptr &&
|
||||
tri_idx < resample_triangles->size() &&
|
||||
!(*resample_triangles)[tri_idx] &&
|
||||
append_preserved_triangle(tri_idx))
|
||||
append_preserved_triangle(tri_idx)) {
|
||||
report_triangle_done();
|
||||
continue;
|
||||
}
|
||||
|
||||
int triangle_min_depth = 0;
|
||||
int triangle_max_depth = max_depth;
|
||||
@@ -4714,8 +4750,10 @@ bool ColorFacetsAnnotation::set_from_triangle_sampler(const ModelVolume
|
||||
0,
|
||||
triangle_min_depth,
|
||||
triangle_max_depth,
|
||||
split_color_threshold))
|
||||
split_color_threshold)) {
|
||||
report_triangle_done();
|
||||
continue;
|
||||
}
|
||||
new_data.bitstream.resize(new_bitstream_start);
|
||||
new_data.colors_rgba.resize(new_color_start);
|
||||
}
|
||||
@@ -4729,7 +4767,9 @@ bool ColorFacetsAnnotation::set_from_triangle_sampler(const ModelVolume
|
||||
triangle_min_depth,
|
||||
triangle_max_depth,
|
||||
split_color_threshold);
|
||||
report_triangle_done();
|
||||
}
|
||||
report_progress(total_triangles);
|
||||
|
||||
new_data.triangles_to_split.shrink_to_fit();
|
||||
new_data.bitstream.shrink_to_fit();
|
||||
|
||||
@@ -849,6 +849,7 @@ using TextureMappingColorSampler = std::function<uint32_t(size_t, const Vec3f &,
|
||||
using TextureMappingColorSubdivisionDepths = std::function<std::pair<int, int>(size_t, const std::array<Vec3f, 3> &)>;
|
||||
using TextureMappingColorLeafResamplePredicate =
|
||||
std::function<bool(size_t, const std::array<Vec3f, 3> &, const std::array<Vec3f, 3> &, uint32_t)>;
|
||||
using TextureMappingColorProgressFn = std::function<void(size_t, size_t)>;
|
||||
|
||||
class ColorFacetsAnnotation final : public ObjectWithTimestamp {
|
||||
public:
|
||||
@@ -891,7 +892,16 @@ public:
|
||||
float split_color_threshold = 0.045f,
|
||||
const TextureMappingColorSubdivisionDepths &subdivision_depths = {},
|
||||
const std::vector<bool> *resample_triangles = nullptr,
|
||||
const TextureMappingColorLeafResamplePredicate &resample_leaf = {});
|
||||
const TextureMappingColorLeafResamplePredicate &resample_leaf = {},
|
||||
const TextureMappingColorProgressFn &progress_fn = {});
|
||||
bool set_from_triangle_sampler(const indexed_triangle_set &its,
|
||||
const TextureMappingColorSampler &sampler,
|
||||
int max_depth = 2,
|
||||
float split_color_threshold = 0.045f,
|
||||
const TextureMappingColorSubdivisionDepths &subdivision_depths = {},
|
||||
const std::vector<bool> *resample_triangles = nullptr,
|
||||
const TextureMappingColorLeafResamplePredicate &resample_leaf = {},
|
||||
const TextureMappingColorProgressFn &progress_fn = {});
|
||||
void get_facet_triangles(const ModelVolume &mv, std::vector<ColorFacetTriangle> &facets) const;
|
||||
void get_facet_triangles(const indexed_triangle_set &its, std::vector<ColorFacetTriangle> &facets) const;
|
||||
|
||||
|
||||
1339
src/libslic3r/ModelTextureDataRemap.cpp
Normal file
1339
src/libslic3r/ModelTextureDataRemap.cpp
Normal file
File diff suppressed because it is too large
Load Diff
75
src/libslic3r/ModelTextureDataRemap.hpp
Normal file
75
src/libslic3r/ModelTextureDataRemap.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
// original author: sentientstardust
|
||||
|
||||
#ifndef slic3r_ModelTextureDataRemap_hpp_
|
||||
#define slic3r_ModelTextureDataRemap_hpp_
|
||||
|
||||
#include "Model.hpp"
|
||||
#include "TriangleMesh.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum class SimplifyColorSource
|
||||
{
|
||||
None,
|
||||
RgbaData,
|
||||
ImageTexture,
|
||||
VertexColors
|
||||
};
|
||||
|
||||
struct SimplifyTextureDataSnapshot
|
||||
{
|
||||
SimplifyColorSource source { SimplifyColorSource::None };
|
||||
indexed_triangle_set source_mesh;
|
||||
std::vector<ColorFacetTriangle> rgba_facets;
|
||||
std::string rgba_metadata_json;
|
||||
std::vector<uint8_t> texture_rgba;
|
||||
std::vector<float> texture_uvs_per_face;
|
||||
std::vector<uint8_t> texture_uv_valid;
|
||||
std::vector<uint8_t> texture_raw_filament_offsets;
|
||||
uint32_t texture_width { 0 };
|
||||
uint32_t texture_height { 0 };
|
||||
uint32_t texture_raw_channels { 0 };
|
||||
std::string texture_raw_metadata_json;
|
||||
int uv_map_generator_version { 0 };
|
||||
std::vector<uint32_t> vertex_colors_rgba;
|
||||
};
|
||||
|
||||
struct SimplifyTextureDataResult
|
||||
{
|
||||
SimplifyColorSource source { SimplifyColorSource::None };
|
||||
bool remap_failed { false };
|
||||
bool used_fallback_rgba { false };
|
||||
std::unique_ptr<ColorFacetsAnnotation> rgba_data;
|
||||
std::vector<uint8_t> texture_rgba;
|
||||
std::vector<float> texture_uvs_per_face;
|
||||
std::vector<uint8_t> texture_uv_valid;
|
||||
std::vector<uint8_t> texture_raw_filament_offsets;
|
||||
uint32_t texture_width { 0 };
|
||||
uint32_t texture_height { 0 };
|
||||
uint32_t texture_raw_channels { 0 };
|
||||
std::string texture_raw_metadata_json;
|
||||
int uv_map_generator_version { 0 };
|
||||
std::vector<uint32_t> vertex_colors_rgba;
|
||||
};
|
||||
|
||||
using SimplifyTextureCancelFn = std::function<void()>;
|
||||
using SimplifyTextureProgressFn = std::function<void(int)>;
|
||||
|
||||
SimplifyTextureDataSnapshot snapshot_simplify_texture_data(const ModelVolume &volume);
|
||||
|
||||
SimplifyTextureDataResult remap_simplify_texture_data(const SimplifyTextureDataSnapshot &snapshot,
|
||||
const indexed_triangle_set &simplified_mesh,
|
||||
const SimplifyTextureCancelFn &throw_on_cancel = {},
|
||||
const SimplifyTextureProgressFn &status_fn = {});
|
||||
|
||||
void apply_simplify_texture_data_result(ModelVolume &volume, SimplifyTextureDataResult &&result);
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
@@ -1,3 +1,5 @@
|
||||
// original author: sentientstardust
|
||||
|
||||
#include "TextureMapping.hpp"
|
||||
#include "ColorSolver.hpp"
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// original author: sentientstardust
|
||||
|
||||
#ifndef slic3r_TextureMapping_hpp_
|
||||
#define slic3r_TextureMapping_hpp_
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
|
||||
#include <glad/gl.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <thread>
|
||||
|
||||
namespace Slic3r::GUI {
|
||||
@@ -163,12 +166,16 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
|
||||
bool is_cancelling = false;
|
||||
bool is_worker_running = false;
|
||||
bool is_result_ready = false;
|
||||
int progress = 0;
|
||||
bool skip_color_conversion_requested = false;
|
||||
bool color_conversion_in_progress = false;
|
||||
float progress = 0.f;
|
||||
{
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
is_cancelling = m_state.status == State::cancelling;
|
||||
is_worker_running = m_state.status == State::running;
|
||||
is_result_ready = bool(m_state.result);
|
||||
skip_color_conversion_requested = m_state.skip_color_conversion_requested;
|
||||
color_conversion_in_progress = m_state.color_conversion_in_progress;
|
||||
progress = m_state.progress;
|
||||
}
|
||||
|
||||
@@ -336,6 +343,21 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
|
||||
m_imgui->disabled_end(); // use_count
|
||||
|
||||
m_imgui->bbl_checkbox(_L("Show wireframe").c_str(), m_show_wireframe);
|
||||
const wxString skip_color_conversion_label = color_conversion_in_progress ?
|
||||
_L("Skip color conversion (in progress)") :
|
||||
_L("Skip color conversion");
|
||||
m_imgui->disabled_begin(!is_worker_running || is_cancelling || skip_color_conversion_requested);
|
||||
m_imgui->push_cancel_button_style();
|
||||
if (m_imgui->bbl_button(skip_color_conversion_label)) {
|
||||
skip_color_conversion_request();
|
||||
} else if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
|
||||
if (skip_color_conversion_requested)
|
||||
ImGui::SetTooltip("%s", _u8L("Color conversion will be skipped.").c_str());
|
||||
else if (!is_worker_running)
|
||||
ImGui::SetTooltip("%s", _u8L("Color conversion can only be skipped while processing.").c_str());
|
||||
}
|
||||
m_imgui->pop_cancel_button_style();
|
||||
m_imgui->disabled_end();
|
||||
|
||||
// draw progress bar
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding,12);
|
||||
@@ -343,9 +365,15 @@ void GLGizmoSimplify::on_render_input_window(float x, float y, float bottom_limi
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,ImVec2(10,20));
|
||||
if (is_worker_running) { // apply or preview
|
||||
// draw progress bar
|
||||
std::string progress_text = GUI::format("%1%", std::to_string(progress)) + "%%";
|
||||
char progress_buffer[32];
|
||||
const float displayed_progress = std::clamp(progress, 0.f, 100.f);
|
||||
if (std::abs(displayed_progress - std::round(displayed_progress)) < 0.05f)
|
||||
std::snprintf(progress_buffer, sizeof(progress_buffer), "%.0f%%", displayed_progress);
|
||||
else
|
||||
std::snprintf(progress_buffer, sizeof(progress_buffer), "%.1f%%", displayed_progress);
|
||||
std::string progress_text = progress_buffer;
|
||||
ImVec2 progress_size(bottom_left_width - space_size, 0.0f);
|
||||
ImGui::BBLProgressBar2(progress / 100., progress_size);
|
||||
ImGui::BBLProgressBar2(displayed_progress / 100.f, progress_size);
|
||||
ImGui::SameLine();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::TextColored(ImVec4(0.42f, 0.42f, 0.42f, 1.00f), progress_text.c_str());
|
||||
@@ -407,6 +435,16 @@ void GLGizmoSimplify::stop_worker_thread_request()
|
||||
m_state.status = State::Status::cancelling;
|
||||
}
|
||||
|
||||
void GLGizmoSimplify::skip_color_conversion_request()
|
||||
{
|
||||
{
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
if (m_state.status == State::running)
|
||||
m_state.skip_color_conversion_requested = true;
|
||||
}
|
||||
request_rerender(true);
|
||||
}
|
||||
|
||||
|
||||
// Following is called from a UI thread when the worker terminates
|
||||
// worker calls it through a CallAfter.
|
||||
@@ -424,8 +462,8 @@ void GLGizmoSimplify::worker_finished()
|
||||
m_worker.join();
|
||||
if (GLGizmoBase::m_state == Off)
|
||||
return;
|
||||
if (m_state.result)
|
||||
init_model(*m_state.result);
|
||||
if (m_state.result && m_state.result->mesh)
|
||||
init_model(*m_state.result->mesh);
|
||||
if (m_state.config != m_configuration || m_state.mv != m_volume) {
|
||||
// Settings were changed, restart the worker immediately.
|
||||
process();
|
||||
@@ -471,13 +509,16 @@ void GLGizmoSimplify::process()
|
||||
m_state.config = m_configuration;
|
||||
m_state.mv = m_volume;
|
||||
m_state.status = State::running;
|
||||
m_state.skip_color_conversion_requested = false;
|
||||
m_state.color_conversion_in_progress = false;
|
||||
|
||||
// Create a copy of current mesh to pass to the worker thread.
|
||||
// Using unique_ptr instead of pass-by-value to avoid an extra
|
||||
// copy (which would happen when passing to std::thread).
|
||||
SimplifyTextureDataSnapshot texture_snapshot = snapshot_simplify_texture_data(*m_volume);
|
||||
auto its = std::make_unique<indexed_triangle_set>(m_volume->mesh().its);
|
||||
|
||||
m_worker = std::thread([this](std::unique_ptr<indexed_triangle_set> its) {
|
||||
m_worker = std::thread([this](std::unique_ptr<indexed_triangle_set> its, SimplifyTextureDataSnapshot texture_snapshot) {
|
||||
|
||||
// Checks that the UI thread did not request cancellation, throws if so.
|
||||
std::function<void(void)> throw_on_cancel = [this]() {
|
||||
@@ -488,11 +529,24 @@ void GLGizmoSimplify::process()
|
||||
|
||||
// Called by worker thread, updates progress bar.
|
||||
// Using CallAfter so the rerequest function is run in UI thread.
|
||||
std::function<void(int)> statusfn = [this](int percent) {
|
||||
std::function<void(float)> statusfn = [this](float percent) {
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
m_state.progress = percent;
|
||||
m_state.progress = std::clamp(percent, 0.f, 100.f);
|
||||
call_after_if_active([this]() { request_rerender(); });
|
||||
};
|
||||
auto set_color_conversion_in_progress = [this](bool in_progress) {
|
||||
{
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
m_state.color_conversion_in_progress = in_progress;
|
||||
}
|
||||
call_after_if_active([this]() { request_rerender(); });
|
||||
};
|
||||
auto throw_on_color_conversion_stop = [this, &throw_on_cancel]() {
|
||||
throw_on_cancel();
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
if (m_state.skip_color_conversion_requested)
|
||||
throw SimplifyColorConversionSkippedException();
|
||||
};
|
||||
|
||||
// Initialize.
|
||||
uint32_t triangle_count = 0;
|
||||
@@ -503,33 +557,64 @@ void GLGizmoSimplify::process()
|
||||
triangle_count = m_state.config.wanted_count;
|
||||
if (! m_state.config.use_count)
|
||||
max_error = m_state.config.max_error;
|
||||
m_state.progress = 0;
|
||||
m_state.progress = 0.f;
|
||||
m_state.result.reset();
|
||||
m_state.color_conversion_in_progress = false;
|
||||
m_state.status = State::Status::running;
|
||||
}
|
||||
|
||||
// Start the actual calculation.
|
||||
try {
|
||||
its_quadric_edge_collapse(*its, triangle_count, &max_error, throw_on_cancel, statusfn);
|
||||
auto decimate_statusfn = [&statusfn](int percent) {
|
||||
statusfn(float(std::clamp(percent, 0, 100)) * 0.9f);
|
||||
};
|
||||
its_quadric_edge_collapse(*its, triangle_count, &max_error, throw_on_cancel, decimate_statusfn);
|
||||
statusfn(90);
|
||||
SimplifyTextureDataResult texture_result;
|
||||
set_color_conversion_in_progress(true);
|
||||
try {
|
||||
throw_on_color_conversion_stop();
|
||||
texture_result =
|
||||
remap_simplify_texture_data(texture_snapshot, *its, throw_on_color_conversion_stop, [&statusfn](int percent) {
|
||||
statusfn(90.f + float(std::clamp(percent, 0, 100)) * 0.1f);
|
||||
});
|
||||
} catch (SimplifyColorConversionSkippedException &) {
|
||||
texture_result = SimplifyTextureDataResult();
|
||||
} catch (...) {
|
||||
set_color_conversion_in_progress(false);
|
||||
throw;
|
||||
}
|
||||
set_color_conversion_in_progress(false);
|
||||
statusfn(100);
|
||||
auto result = std::make_unique<SimplifyResult>();
|
||||
result->mesh = std::move(its);
|
||||
result->texture_data = std::move(texture_result);
|
||||
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
if (m_state.status == State::Status::running) {
|
||||
m_state.status = State::Status::idle;
|
||||
m_state.color_conversion_in_progress = false;
|
||||
m_state.result = std::move(result);
|
||||
} else if (m_state.status == State::Status::cancelling) {
|
||||
m_state.color_conversion_in_progress = false;
|
||||
m_state.status = State::Status::idle;
|
||||
}
|
||||
} catch (SimplifyCanceledException &) {
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
m_state.color_conversion_in_progress = false;
|
||||
m_state.status = State::idle;
|
||||
}
|
||||
|
||||
std::lock_guard lk(m_state_mutex);
|
||||
if (m_state.status == State::Status::running) {
|
||||
// We were not cancelled, the result is valid.
|
||||
m_state.status = State::Status::idle;
|
||||
m_state.result = std::move(its);
|
||||
}
|
||||
|
||||
// Update UI. Use CallAfter so the function is run on UI thread.
|
||||
call_after_if_active([this]() { worker_finished(); });
|
||||
}, std::move(its));
|
||||
}, std::move(its), std::move(texture_snapshot));
|
||||
}
|
||||
|
||||
void GLGizmoSimplify::apply_simplify() {
|
||||
|
||||
if (!m_state.result || !m_state.result->mesh)
|
||||
return;
|
||||
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
int object_idx = selection.get_object_idx();
|
||||
|
||||
@@ -540,7 +625,10 @@ void GLGizmoSimplify::apply_simplify() {
|
||||
ModelVolume* mv = get_model_volume(selection, wxGetApp().model());
|
||||
assert(mv == m_volume);
|
||||
|
||||
mv->set_mesh(std::move(*m_state.result));
|
||||
const bool remap_failed = m_state.result->texture_data.remap_failed;
|
||||
const bool used_fallback_rgba = m_state.result->texture_data.used_fallback_rgba;
|
||||
mv->set_mesh(std::move(*m_state.result->mesh));
|
||||
apply_simplify_texture_data_result(*mv, std::move(m_state.result->texture_data));
|
||||
m_state.result.reset();
|
||||
mv->calculate_convex_hull();
|
||||
mv->invalidate_convex_hull_2d();
|
||||
@@ -550,6 +638,17 @@ void GLGizmoSimplify::apply_simplify() {
|
||||
|
||||
// fix hollowing, sla support points, modifiers, ...
|
||||
plater->changed_mesh(object_idx);
|
||||
if (used_fallback_rgba) {
|
||||
plater->get_notification_manager()->push_notification(
|
||||
NotificationType::CustomNotification,
|
||||
NotificationManager::NotificationLevel::PrintInfoNotificationLevel,
|
||||
_u8L("Image texture UVs could not be regenerated after simplification; texture colors were preserved as RGBA data."));
|
||||
} else if (remap_failed) {
|
||||
plater->get_notification_manager()->push_notification(
|
||||
NotificationType::CustomNotification,
|
||||
NotificationManager::NotificationLevel::PrintInfoNotificationLevel,
|
||||
_u8L("Image texture UVs could not be regenerated after simplification; stale texture data was cleared."));
|
||||
}
|
||||
// Fix warning icon in object list
|
||||
wxGetApp().obj_list()->update_item_error_icon(object_idx, -1);
|
||||
close();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// which overrides our localization "L" macro.
|
||||
#include "GLGizmoBase.hpp"
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
#include "libslic3r/ModelTextureDataRemap.hpp"
|
||||
#include "admesh/stl.h" // indexed_triangle_set
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
@@ -46,6 +47,7 @@ private:
|
||||
|
||||
void process();
|
||||
void stop_worker_thread_request();
|
||||
void skip_color_conversion_request();
|
||||
void worker_finished();
|
||||
|
||||
void create_gui_cfg();
|
||||
@@ -86,6 +88,12 @@ private:
|
||||
|
||||
// Following struct is accessed by both UI and worker thread.
|
||||
// Accesses protected by a mutex.
|
||||
struct SimplifyResult
|
||||
{
|
||||
std::unique_ptr<indexed_triangle_set> mesh;
|
||||
SimplifyTextureDataResult texture_data;
|
||||
};
|
||||
|
||||
struct State {
|
||||
enum Status {
|
||||
idle,
|
||||
@@ -94,10 +102,12 @@ private:
|
||||
};
|
||||
|
||||
Status status = idle;
|
||||
int progress = 0; // percent of done work
|
||||
float progress = 0.f; // percent of done work
|
||||
Configuration config; // Configuration we started with.
|
||||
const ModelVolume* mv = nullptr;
|
||||
std::unique_ptr<indexed_triangle_set> result;
|
||||
bool skip_color_conversion_requested = false;
|
||||
bool color_conversion_in_progress = false;
|
||||
std::unique_ptr<SimplifyResult> result;
|
||||
};
|
||||
|
||||
std::thread m_worker;
|
||||
@@ -141,6 +151,15 @@ private:
|
||||
return L("Model simplification has been canceled");
|
||||
}
|
||||
};
|
||||
|
||||
class SimplifyColorConversionSkippedException: public std::exception
|
||||
{
|
||||
public:
|
||||
const char *what() const throw()
|
||||
{
|
||||
return L("Color conversion has been skipped");
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
|
||||
Reference in New Issue
Block a user