Prevent calculating simulated result colors on main thread

This commit is contained in:
sentientstardust
2026-05-05 23:38:21 +01:00
parent 4ac7f4380e
commit 303ec41cb2
6 changed files with 528 additions and 51 deletions

View File

@@ -4696,9 +4696,13 @@ bool ColorFacetsAnnotation::set_from_triangle_sampler(const ModelVolume
}
void ColorFacetsAnnotation::get_facet_triangles(const ModelVolume &mv, std::vector<ColorFacetTriangle> &facets) const
{
this->get_facet_triangles(mv.mesh().its, facets);
}
void ColorFacetsAnnotation::get_facet_triangles(const indexed_triangle_set &its, std::vector<ColorFacetTriangle> &facets) const
{
facets.clear();
const indexed_triangle_set &its = mv.mesh().its;
if (its.vertices.empty() || its.indices.empty())
return;

View File

@@ -893,6 +893,7 @@ public:
const std::vector<bool> *resample_triangles = nullptr,
const TextureMappingColorLeafResamplePredicate &resample_leaf = {});
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;
private:
explicit ColorFacetsAnnotation() = default;

View File

@@ -696,6 +696,8 @@ void GLVolume::simple_render(GLShaderProgram* shader,
color_volume = has_mmu_segmentation;
size_t preview_visual_signature = texture_preview_settings_signature(num_physical, texture_mgr);
preview_visual_signature ^= texture_preview_simulation_generation_signature() + 0x9e3779b97f4a7c15ull +
(preview_visual_signature << 6) + (preview_visual_signature >> 2);
preview_visual_signature ^= model_volume_texture_preview_signature(*model_volume) + 0x9e3779b97f4a7c15ull +
(preview_visual_signature << 6) + (preview_visual_signature >> 2);
preview_visual_signature ^= model_volume->imported_vertex_colors_rgba.size() + 0x9e3779b97f4a7c15ull +
@@ -912,8 +914,17 @@ void GLVolume::render_mmu_texture_preview(const Transform3d &view_matrix,
return preview_colors;
};
const bool original_mesh_preview_can_defer_source_texture =
use_original_mesh_texture_preview &&
texture_preview_simulation_enabled_for_filament(base_filament_id, num_physical, texture_mgr);
const bool mmuseg_preview_can_defer_source_texture =
!use_original_mesh_texture_preview &&
!mmuseg_texture_preview_models.empty() &&
texture_preview_simulation_enabled_for_all_filaments(mmuseg_texture_preview_filament_ids, num_physical, texture_mgr);
if ((use_original_mesh_texture_preview || !mmuseg_texture_preview_models.empty()) &&
ensure_model_volume_texture_preview(*model_volume, mmuseg_texture_preview, mmuseg_texture_preview_signature)) {
(original_mesh_preview_can_defer_source_texture ||
mmuseg_preview_can_defer_source_texture ||
ensure_model_volume_texture_preview(*model_volume, mmuseg_texture_preview, mmuseg_texture_preview_signature))) {
if (use_original_mesh_texture_preview) {
const int extruder_id = model_volume->extruder_id();
const ColorRGBA fallback_color = extruder_colors.empty() ? ColorRGBA(0.15f, 0.65f, 0.6f, 1.f) : extruder_colors.front();

View File

@@ -1685,6 +1685,8 @@ void TriangleSelectorPatch::update_render_data()
const TextureMappingManager *texture_mgr = wxGetApp().preset_bundle != nullptr ?
&wxGetApp().preset_bundle->texture_mapping_zones : nullptr;
m_texture_preview_visual_signature = texture_preview_settings_signature(num_physical, texture_mgr);
m_texture_preview_visual_signature ^= texture_preview_simulation_generation_signature() + 0x9e3779b97f4a7c15ull +
(m_texture_preview_visual_signature << 6) + (m_texture_preview_visual_signature >> 2);
if (m_texture_mapping_color_preview != nullptr && !m_texture_mapping_color_preview->empty()) {
build_mmu_vertex_color_preview_models(*m_model_volume,
triangles_per_type,
@@ -1842,7 +1844,9 @@ void TriangleSelectorPatch::render_texture_preview(const Transform3d& m
const size_t num_physical = std::max(0, wxGetApp().filaments_cnt());
const TextureMappingManager *texture_mgr = wxGetApp().preset_bundle != nullptr ?
&wxGetApp().preset_bundle->texture_mapping_zones : nullptr;
const size_t current_visual_signature = texture_preview_settings_signature(num_physical, texture_mgr);
size_t current_visual_signature = texture_preview_settings_signature(num_physical, texture_mgr);
current_visual_signature ^= texture_preview_simulation_generation_signature() + 0x9e3779b97f4a7c15ull +
(current_visual_signature << 6) + (current_visual_signature >> 2);
if (current_visual_signature != m_texture_preview_visual_signature) {
TriangleSelectorPatch *self = const_cast<TriangleSelectorPatch *>(this);
self->request_update_render_data(true);
@@ -1862,8 +1866,12 @@ void TriangleSelectorPatch::render_texture_preview(const Transform3d& m
return preview_colors;
};
const bool texture_preview_can_defer_source_texture =
!m_texture_preview_models.empty() &&
texture_preview_simulation_enabled_for_all_filaments(m_texture_preview_filament_ids, num_physical, texture_mgr);
if (!m_texture_preview_models.empty() &&
ensure_model_volume_texture_preview(*m_model_volume, m_texture_preview, m_texture_preview_signature)) {
(texture_preview_can_defer_source_texture ||
ensure_model_volume_texture_preview(*m_model_volume, m_texture_preview, m_texture_preview_signature))) {
render_model_texture_preview_models(m_texture_preview_models,
adjusted_preview_colors(m_texture_preview_colors),
m_texture_preview_filament_ids,

View File

@@ -115,6 +115,21 @@ struct TexturePreviewSimulationCacheEntry
std::future<TexturePreviewSimulationResult> pending_future;
};
struct TexturePreviewVertexColorSimulationResult
{
size_t signature { 0 };
GUI::GLModel::Geometry geometry;
};
struct TexturePreviewVertexColorSimulationCacheEntry
{
size_t ready_signature { 0 };
size_t pending_signature { 0 };
bool ready_generation_reported { false };
std::optional<GUI::GLModel::Geometry> ready_geometry;
std::future<TexturePreviewVertexColorSimulationResult> pending_future;
};
bool model_volume_has_texture_preview_data_impl(const ModelVolume &model_volume)
{
return !model_volume.imported_texture_rgba.empty() &&
@@ -1606,6 +1621,24 @@ std::vector<std::future<TexturePreviewSimulationResult>> &abandoned_texture_prev
return *futures;
}
std::unordered_map<size_t, std::shared_ptr<TexturePreviewVertexColorSimulationCacheEntry>> &texture_preview_vertex_color_simulation_cache()
{
static auto *cache = new std::unordered_map<size_t, std::shared_ptr<TexturePreviewVertexColorSimulationCacheEntry>>();
return *cache;
}
std::vector<std::future<TexturePreviewVertexColorSimulationResult>> &abandoned_texture_preview_vertex_color_futures()
{
static auto *futures = new std::vector<std::future<TexturePreviewVertexColorSimulationResult>>();
return *futures;
}
size_t &texture_preview_vertex_color_simulation_generation()
{
static auto *generation = new size_t(0);
return *generation;
}
void discard_ready_texture_preview_future(TexturePreviewSimulationCacheEntry &entry)
{
if (!entry.pending_future.valid() ||
@@ -1619,6 +1652,19 @@ void discard_ready_texture_preview_future(TexturePreviewSimulationCacheEntry &en
entry.pending_signature = 0;
}
void discard_ready_texture_preview_vertex_color_future(TexturePreviewVertexColorSimulationCacheEntry &entry)
{
if (!entry.pending_future.valid() ||
entry.pending_future.wait_for(std::chrono::seconds(0)) != std::future_status::ready)
return;
try {
(void) entry.pending_future.get();
} catch (...) {
}
entry.pending_signature = 0;
}
bool prune_abandoned_texture_preview_futures()
{
bool pending = false;
@@ -1643,11 +1689,36 @@ bool prune_abandoned_texture_preview_futures()
return pending;
}
bool prune_abandoned_texture_preview_vertex_color_futures()
{
bool pending = false;
auto &futures = abandoned_texture_preview_vertex_color_futures();
for (auto it = futures.begin(); it != futures.end();) {
if (!it->valid()) {
it = futures.erase(it);
continue;
}
if (it->wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
try {
(void) it->get();
} catch (...) {
}
it = futures.erase(it);
} else {
pending = true;
++it;
}
}
return pending;
}
} // namespace
void clear_texture_preview_simulation_cache()
{
prune_abandoned_texture_preview_futures();
prune_abandoned_texture_preview_vertex_color_futures();
auto &cache = texture_preview_simulation_cache();
for (auto it = cache.begin(); it != cache.end();) {
@@ -1673,13 +1744,37 @@ void clear_texture_preview_simulation_cache()
}
it = cache.erase(it);
}
auto &vertex_color_cache = texture_preview_vertex_color_simulation_cache();
for (auto it = vertex_color_cache.begin(); it != vertex_color_cache.end();) {
std::shared_ptr<TexturePreviewVertexColorSimulationCacheEntry> &entry = it->second;
if (entry == nullptr) {
it = vertex_color_cache.erase(it);
continue;
}
entry->ready_geometry.reset();
entry->ready_signature = 0;
entry->pending_signature = 0;
entry->ready_generation_reported = false;
if (entry->pending_future.valid()) {
if (entry->pending_future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
discard_ready_texture_preview_vertex_color_future(*entry);
} else {
abandoned_texture_preview_vertex_color_futures().emplace_back(std::move(entry->pending_future));
}
}
it = vertex_color_cache.erase(it);
}
}
namespace {
bool texture_preview_simulation_is_pending_impl()
{
const bool abandoned_pending = prune_abandoned_texture_preview_futures();
bool pending = prune_abandoned_texture_preview_futures();
pending = prune_abandoned_texture_preview_vertex_color_futures() || pending;
auto &cache = texture_preview_simulation_cache();
for (auto it = cache.begin(); it != cache.end();) {
const std::shared_ptr<TexturePreviewSimulationCacheEntry> &entry = it->second;
@@ -1693,8 +1788,11 @@ bool texture_preview_simulation_is_pending_impl()
continue;
}
if (entry->pending_future.wait_for(std::chrono::seconds(0)) != std::future_status::ready)
return true;
if (entry->pending_future.wait_for(std::chrono::seconds(0)) != std::future_status::ready) {
pending = true;
++it;
continue;
}
if (entry->texture == nullptr && entry->pending_signature == 0) {
discard_ready_texture_preview_future(*entry);
@@ -1704,7 +1802,54 @@ bool texture_preview_simulation_is_pending_impl()
++it;
}
return abandoned_pending;
auto &vertex_color_cache = texture_preview_vertex_color_simulation_cache();
for (auto it = vertex_color_cache.begin(); it != vertex_color_cache.end();) {
std::shared_ptr<TexturePreviewVertexColorSimulationCacheEntry> &entry = it->second;
if (entry == nullptr) {
it = vertex_color_cache.erase(it);
continue;
}
bool completed_future = false;
if (entry->pending_future.valid()) {
if (entry->pending_future.wait_for(std::chrono::seconds(0)) != std::future_status::ready) {
pending = true;
++it;
continue;
}
completed_future = true;
try {
TexturePreviewVertexColorSimulationResult result = entry->pending_future.get();
if (result.signature == entry->pending_signature && !result.geometry.is_empty()) {
entry->ready_signature = result.signature;
entry->ready_geometry = std::move(result.geometry);
entry->ready_generation_reported = false;
}
} catch (...) {
}
entry->pending_signature = 0;
}
if (entry->ready_geometry.has_value()) {
pending = true;
if (!entry->ready_generation_reported) {
++texture_preview_vertex_color_simulation_generation();
entry->ready_generation_reported = true;
}
++it;
continue;
}
if (completed_future) {
pending = true;
++texture_preview_vertex_color_simulation_generation();
}
it = vertex_color_cache.erase(it);
}
return pending;
}
size_t texture_preview_simulation_cache_key(const ModelVolume &model_volume, unsigned int filament_id)
@@ -1873,24 +2018,23 @@ bool build_texture_preview_model_for_state(const ModelVolume
return true;
}
bool build_vertex_color_preview_model_for_state(const ModelVolume &model_volume,
const std::vector<TriangleSelector::FacetStateTriangle> &state_triangles,
const TexturePreviewSimulationSettings *simulation_settings,
GUI::GLModel &out_model)
bool build_vertex_color_preview_geometry_for_state(const indexed_triangle_set &its,
const std::vector<uint32_t> &vertex_colors_rgba,
const std::vector<TriangleSelector::FacetStateTriangle> &state_triangles,
const TexturePreviewSimulationSettings *simulation_settings,
const ColorRGBA &background_color,
GUI::GLModel::Geometry &geometry)
{
if (!model_volume_has_vertex_color_preview_data(model_volume) || state_triangles.empty())
if (vertex_colors_rgba.empty() || vertex_colors_rgba.size() != its.vertices.size() || state_triangles.empty())
return false;
const indexed_triangle_set &its = model_volume.mesh().its;
GUI::GLModel::Geometry geometry;
geometry.format = { GUI::GLModel::Geometry::EPrimitiveType::Triangles, GUI::GLModel::Geometry::EVertexLayout::P3N3C4 };
geometry.reserve_vertices(state_triangles.size() * 3);
geometry.reserve_indices(state_triangles.size() * 3);
std::unordered_map<uint32_t, ColorRGBA> simulated_color_cache;
if (simulation_settings != nullptr)
simulated_color_cache.reserve(std::min(model_volume.imported_vertex_colors_rgba.size(), size_t(65536)));
const ColorRGBA background_color = texture_mapping_background_color_for_preview(model_volume);
simulated_color_cache.reserve(std::min(vertex_colors_rgba.size(), size_t(65536)));
auto preview_color = [simulation_settings, &simulated_color_cache, background_color](const ColorRGBA &source_color) {
const ColorRGBA blended_source =
composite_texture_mapping_color_over_background_for_preview(source_color, background_color);
@@ -1928,18 +2072,18 @@ bool build_vertex_color_preview_model_for_state(const ModelVolume
if (size_t(source_indices[0]) >= its.vertices.size() ||
size_t(source_indices[1]) >= its.vertices.size() ||
size_t(source_indices[2]) >= its.vertices.size() ||
size_t(source_indices[0]) >= model_volume.imported_vertex_colors_rgba.size() ||
size_t(source_indices[1]) >= model_volume.imported_vertex_colors_rgba.size() ||
size_t(source_indices[2]) >= model_volume.imported_vertex_colors_rgba.size())
size_t(source_indices[0]) >= vertex_colors_rgba.size() ||
size_t(source_indices[1]) >= vertex_colors_rgba.size() ||
size_t(source_indices[2]) >= vertex_colors_rgba.size())
continue;
const Vec3f source_p0 = its.vertices[size_t(source_indices[0])].cast<float>();
const Vec3f source_p1 = its.vertices[size_t(source_indices[1])].cast<float>();
const Vec3f source_p2 = its.vertices[size_t(source_indices[2])].cast<float>();
const std::array<ColorRGBA, 3> source_colors = {
source_vertex_color(model_volume.imported_vertex_colors_rgba[size_t(source_indices[0])]),
source_vertex_color(model_volume.imported_vertex_colors_rgba[size_t(source_indices[1])]),
source_vertex_color(model_volume.imported_vertex_colors_rgba[size_t(source_indices[2])])
source_vertex_color(vertex_colors_rgba[size_t(source_indices[0])]),
source_vertex_color(vertex_colors_rgba[size_t(source_indices[1])]),
source_vertex_color(vertex_colors_rgba[size_t(source_indices[2])])
};
Vec3f normal = (triangle.vertices[1] - triangle.vertices[0]).cross(triangle.vertices[2] - triangle.vertices[0]);
@@ -1971,6 +2115,26 @@ bool build_vertex_color_preview_model_for_state(const ModelVolume
if (geometry.is_empty())
return false;
return true;
}
bool build_vertex_color_preview_model_for_state(const ModelVolume &model_volume,
const std::vector<TriangleSelector::FacetStateTriangle> &state_triangles,
const TexturePreviewSimulationSettings *simulation_settings,
GUI::GLModel &out_model)
{
if (!model_volume_has_vertex_color_preview_data(model_volume) || state_triangles.empty())
return false;
GUI::GLModel::Geometry geometry;
if (!build_vertex_color_preview_geometry_for_state(model_volume.mesh().its,
model_volume.imported_vertex_colors_rgba,
state_triangles,
simulation_settings,
texture_mapping_background_color_for_preview(model_volume),
geometry))
return false;
out_model.init_from(std::move(geometry));
return true;
}
@@ -2058,21 +2222,19 @@ bool preview_polygon_has_area(const std::vector<Vec3f> &polygon, const Vec3f &no
return area > k_epsilon;
}
bool build_texture_mapping_color_preview_model_for_state(
const ModelVolume &model_volume,
bool build_texture_mapping_color_preview_geometry_for_state(
const indexed_triangle_set &its,
const ColorFacetsAnnotation &color_source,
const std::vector<TriangleSelector::FacetStateTriangle> &state_triangles,
const TexturePreviewSimulationSettings *simulation_settings,
GUI::GLModel &out_model,
const ColorFacetsAnnotation *texture_mapping_color_facets_override = nullptr)
const ColorRGBA &background_color,
GUI::GLModel::Geometry &geometry)
{
const ColorFacetsAnnotation *color_source = texture_mapping_color_facets_override;
if (color_source == nullptr || color_source->empty())
color_source = &model_volume.texture_mapping_color_facets;
if (color_source == nullptr || color_source->empty() || state_triangles.empty())
if (color_source.empty() || state_triangles.empty())
return false;
std::vector<ColorFacetTriangle> color_facets;
color_source->get_facet_triangles(model_volume, color_facets);
color_source.get_facet_triangles(its, color_facets);
if (color_facets.empty())
return false;
@@ -2081,7 +2243,6 @@ bool build_texture_mapping_color_preview_model_for_state(
for (size_t idx = 0; idx < color_facets.size(); ++idx)
facets_by_source_triangle[color_facets[idx].source_triangle].emplace_back(idx);
GUI::GLModel::Geometry geometry;
geometry.format = { GUI::GLModel::Geometry::EPrimitiveType::Triangles, GUI::GLModel::Geometry::EVertexLayout::P3N3C4 };
geometry.reserve_vertices(color_facets.size() * 3);
geometry.reserve_indices(color_facets.size() * 3);
@@ -2089,7 +2250,6 @@ bool build_texture_mapping_color_preview_model_for_state(
std::unordered_map<uint32_t, ColorRGBA> simulated_color_cache;
if (simulation_settings != nullptr)
simulated_color_cache.reserve(std::min(color_facets.size(), size_t(65536)));
const ColorRGBA background_color = texture_mapping_background_color_for_preview(model_volume, color_source);
auto preview_color = [simulation_settings, &simulated_color_cache, background_color](const ColorRGBA &source_color) {
const ColorRGBA blended_source =
composite_texture_mapping_color_over_background_for_preview(source_color, background_color);
@@ -2178,10 +2338,252 @@ bool build_texture_mapping_color_preview_model_for_state(
if (geometry.is_empty())
return false;
return true;
}
bool build_texture_mapping_color_preview_model_for_state(
const ModelVolume &model_volume,
const std::vector<TriangleSelector::FacetStateTriangle> &state_triangles,
const TexturePreviewSimulationSettings *simulation_settings,
GUI::GLModel &out_model,
const ColorFacetsAnnotation *texture_mapping_color_facets_override = nullptr)
{
const ColorFacetsAnnotation *color_source = texture_mapping_color_facets_override;
if (color_source == nullptr || color_source->empty())
color_source = &model_volume.texture_mapping_color_facets;
if (color_source == nullptr || color_source->empty() || state_triangles.empty())
return false;
GUI::GLModel::Geometry geometry;
if (!build_texture_mapping_color_preview_geometry_for_state(model_volume.mesh().its,
*color_source,
state_triangles,
simulation_settings,
texture_mapping_background_color_for_preview(model_volume, color_source),
geometry))
return false;
out_model.init_from(std::move(geometry));
return true;
}
size_t texture_preview_state_triangles_signature(const std::vector<TriangleSelector::FacetStateTriangle> &state_triangles)
{
size_t signature = 1469598103934665603ull;
auto mix = [&signature](size_t value) {
signature ^= value + 0x9e3779b97f4a7c15ull + (signature << 6) + (signature >> 2);
};
auto mix_float = [&mix](float value) {
const float safe_value = std::isfinite(value) ? value : 0.f;
mix(std::hash<int>{}(int(std::lround(safe_value * 1000000.f))));
};
mix(state_triangles.size());
for (const TriangleSelector::FacetStateTriangle &triangle : state_triangles) {
mix(std::hash<int>{}(triangle.source_triangle));
for (const Vec3f &vertex : triangle.vertices) {
mix_float(vertex.x());
mix_float(vertex.y());
mix_float(vertex.z());
}
}
return signature;
}
size_t texture_preview_vertex_color_source_signature(const ModelVolume &model_volume,
const std::vector<TriangleSelector::FacetStateTriangle> &state_triangles)
{
size_t signature = 1469598103934665603ull;
auto mix = [&signature](size_t value) {
signature ^= value + 0x9e3779b97f4a7c15ull + (signature << 6) + (signature >> 2);
};
mix(reinterpret_cast<size_t>(model_volume.mesh_ptr().get()));
mix(model_volume.mesh().its.vertices.size());
mix(model_volume.mesh().its.indices.size());
mix(model_volume.imported_vertex_colors_rgba.size());
mix(reinterpret_cast<size_t>(model_volume.imported_vertex_colors_rgba.data()));
mix(texture_preview_state_triangles_signature(state_triangles));
const ColorRGBA background = texture_mapping_background_color_for_preview(model_volume);
auto background_signature_component = [](float value) {
return size_t(std::clamp(value, 0.f, 1.f) * 255.f + 0.5f);
};
mix(background_signature_component(background.r()));
mix(background_signature_component(background.g()));
mix(background_signature_component(background.b()));
return signature;
}
size_t texture_preview_color_facets_source_signature(const ModelVolume &model_volume,
const ColorFacetsAnnotation &color_source,
const std::vector<TriangleSelector::FacetStateTriangle> &state_triangles)
{
size_t signature = 1469598103934665603ull;
auto mix = [&signature](size_t value) {
signature ^= value + 0x9e3779b97f4a7c15ull + (signature << 6) + (signature >> 2);
};
mix(reinterpret_cast<size_t>(model_volume.mesh_ptr().get()));
mix(model_volume.mesh().its.vertices.size());
mix(model_volume.mesh().its.indices.size());
const TriangleColorSplittingData &data = color_source.get_data();
mix(data.triangles_to_split.size());
mix(data.bitstream.size());
mix(data.colors_rgba.size());
for (const ColorTriangleBitStreamMapping &mapping : data.triangles_to_split) {
mix(size_t(mapping.triangle_idx));
mix(size_t(mapping.bitstream_start_idx));
mix(size_t(mapping.color_start_idx));
}
for (const bool bit : data.bitstream)
mix(bit ? 1u : 0u);
for (const uint32_t color : data.colors_rgba)
mix(size_t(color));
for (const char ch : data.metadata_json)
mix(size_t(static_cast<unsigned char>(ch)));
mix(texture_preview_state_triangles_signature(state_triangles));
const ColorRGBA background = texture_mapping_background_color_for_preview(model_volume, &color_source);
auto background_signature_component = [](float value) {
return size_t(std::clamp(value, 0.f, 1.f) * 255.f + 0.5f);
};
mix(background_signature_component(background.r()));
mix(background_signature_component(background.g()));
mix(background_signature_component(background.b()));
return signature;
}
size_t texture_preview_vertex_color_simulation_cache_key(const ModelVolume &model_volume, unsigned int filament_id, size_t source_kind)
{
size_t key = texture_preview_simulation_cache_key(model_volume, filament_id);
key ^= std::hash<size_t>{}(source_kind) + 0x9e3779b97f4a7c15ull + (key << 6) + (key >> 2);
return key;
}
bool consume_or_queue_vertex_color_simulation(size_t cache_key,
size_t simulation_signature,
std::function<TexturePreviewVertexColorSimulationResult()> build_result,
GUI::GLModel &out_model)
{
auto &cache = texture_preview_vertex_color_simulation_cache();
std::shared_ptr<TexturePreviewVertexColorSimulationCacheEntry> &entry_ref = cache[cache_key];
if (entry_ref == nullptr)
entry_ref = std::make_shared<TexturePreviewVertexColorSimulationCacheEntry>();
TexturePreviewVertexColorSimulationCacheEntry &entry = *entry_ref;
if (entry.pending_future.valid() && entry.pending_future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
try {
TexturePreviewVertexColorSimulationResult result = entry.pending_future.get();
if (result.signature == entry.pending_signature && !result.geometry.is_empty()) {
entry.ready_signature = result.signature;
entry.ready_geometry = std::move(result.geometry);
entry.ready_generation_reported = false;
}
} catch (...) {
}
entry.pending_signature = 0;
}
if (entry.ready_geometry.has_value() && entry.ready_signature == simulation_signature) {
out_model.init_from(std::move(*entry.ready_geometry));
cache.erase(cache_key);
return true;
}
if (!entry.pending_future.valid()) {
entry.ready_geometry.reset();
entry.ready_signature = 0;
entry.ready_generation_reported = false;
entry.pending_signature = simulation_signature;
entry.pending_future = std::async(std::launch::async, std::move(build_result));
}
return false;
}
bool build_simulated_vertex_color_preview_model_for_state(
const ModelVolume &model_volume,
const std::vector<TriangleSelector::FacetStateTriangle> &state_triangles,
unsigned int filament_id,
const TexturePreviewSimulationSettings &simulation_settings,
GUI::GLModel &out_model)
{
if (!model_volume_has_vertex_color_preview_data(model_volume) || state_triangles.empty())
return false;
const size_t source_signature = texture_preview_vertex_color_source_signature(model_volume, state_triangles);
const size_t simulation_signature = texture_preview_simulation_signature(model_volume, source_signature, simulation_settings);
const size_t cache_key = texture_preview_vertex_color_simulation_cache_key(model_volume, filament_id, 1u);
std::shared_ptr<const TriangleMesh> mesh = model_volume.mesh_ptr();
std::vector<uint32_t> vertex_colors(model_volume.imported_vertex_colors_rgba.begin(), model_volume.imported_vertex_colors_rgba.end());
std::vector<TriangleSelector::FacetStateTriangle> triangles = state_triangles;
const ColorRGBA background_color = texture_mapping_background_color_for_preview(model_volume);
TexturePreviewSimulationSettings settings = simulation_settings;
return consume_or_queue_vertex_color_simulation(cache_key,
simulation_signature,
[simulation_signature,
mesh = std::move(mesh),
vertex_colors = std::move(vertex_colors),
triangles = std::move(triangles),
background_color,
settings = std::move(settings)]() mutable {
TexturePreviewVertexColorSimulationResult result;
result.signature = simulation_signature;
prepare_texture_preview_simulation_settings(settings);
build_vertex_color_preview_geometry_for_state(mesh->its,
vertex_colors,
triangles,
&settings,
background_color,
result.geometry);
return result;
},
out_model);
}
bool build_simulated_texture_mapping_color_preview_model_for_state(
const ModelVolume &model_volume,
const std::vector<TriangleSelector::FacetStateTriangle> &state_triangles,
unsigned int filament_id,
const TexturePreviewSimulationSettings &simulation_settings,
GUI::GLModel &out_model,
const ColorFacetsAnnotation *texture_mapping_color_facets_override = nullptr)
{
const ColorFacetsAnnotation *color_source = texture_mapping_color_facets_override;
if (color_source == nullptr || color_source->empty())
color_source = &model_volume.texture_mapping_color_facets;
if (color_source == nullptr || color_source->empty() || state_triangles.empty())
return false;
const size_t source_signature = texture_preview_color_facets_source_signature(model_volume, *color_source, state_triangles);
const size_t simulation_signature = texture_preview_simulation_signature(model_volume, source_signature, simulation_settings);
const size_t cache_key = texture_preview_vertex_color_simulation_cache_key(model_volume, filament_id, 2u);
std::shared_ptr<const TriangleMesh> mesh = model_volume.mesh_ptr();
ColorFacetsAnnotation color_source_copy(*color_source);
std::vector<TriangleSelector::FacetStateTriangle> triangles = state_triangles;
const ColorRGBA background_color = texture_mapping_background_color_for_preview(model_volume, color_source);
TexturePreviewSimulationSettings settings = simulation_settings;
return consume_or_queue_vertex_color_simulation(cache_key,
simulation_signature,
[simulation_signature,
mesh = std::move(mesh),
color_source_copy = std::move(color_source_copy),
triangles = std::move(triangles),
background_color,
settings = std::move(settings)]() mutable {
TexturePreviewVertexColorSimulationResult result;
result.signature = simulation_signature;
prepare_texture_preview_simulation_settings(settings);
build_texture_mapping_color_preview_geometry_for_state(mesh->its,
color_source_copy,
triangles,
&settings,
background_color,
result.geometry);
return result;
},
out_model);
}
float normalize_angle(float angle)
{
if (!std::isfinite(angle))
@@ -2708,6 +3110,33 @@ bool texture_preview_simulation_is_pending()
return texture_preview_simulation_is_pending_impl();
}
bool texture_preview_simulation_enabled_for_filament(unsigned int filament_id,
size_t num_physical,
const TextureMappingManager *texture_mgr)
{
const std::vector<std::string> physical_colors = physical_filament_colors_for_texture_preview(num_physical);
return texture_preview_simulation_settings_for_filament(filament_id, num_physical, texture_mgr, physical_colors).has_value();
}
bool texture_preview_simulation_enabled_for_all_filaments(const std::vector<unsigned int> &filament_ids,
size_t num_physical,
const TextureMappingManager *texture_mgr)
{
if (filament_ids.empty())
return false;
const std::vector<std::string> physical_colors = physical_filament_colors_for_texture_preview(num_physical);
for (const unsigned int filament_id : filament_ids)
if (!texture_preview_simulation_settings_for_filament(filament_id, num_physical, texture_mgr, physical_colors).has_value())
return false;
return true;
}
size_t texture_preview_simulation_generation_signature()
{
return texture_preview_vertex_color_simulation_generation();
}
bool build_mmu_texture_preview_models(
const ModelVolume &model_volume,
const std::vector<std::vector<TriangleSelector::FacetStateTriangle>> &triangles_per_type,
@@ -2803,27 +3232,44 @@ bool build_mmu_vertex_color_preview_models(
if (!build_surface_gradient_vertex_color_preview_model_for_state(triangles_per_type[state_id], *settings, world_matrix, model))
continue;
} else {
std::optional<TexturePreviewSimulationSettings> simulation_settings =
texture_preview_simulation_settings_for_filament(filament_id, num_physical, texture_mgr, physical_colors);
if (simulation_settings)
prepare_texture_preview_simulation_settings(*simulation_settings);
const bool has_texture_mapping_color_preview =
has_texture_mapping_color_override || model_volume_has_texture_mapping_color_preview_data(model_volume);
if (!has_texture_mapping_color_preview && !model_volume_has_vertex_color_preview_data(model_volume))
continue;
std::optional<TexturePreviewSimulationSettings> simulation_settings =
texture_preview_simulation_settings_for_filament(filament_id, num_physical, texture_mgr, physical_colors);
if (has_texture_mapping_color_preview) {
const ColorFacetsAnnotation *preview_override =
has_texture_mapping_color_override ? texture_mapping_color_facets_override : nullptr;
if (!build_texture_mapping_color_preview_model_for_state(model_volume,
triangles_per_type[state_id],
simulation_settings ? &*simulation_settings : nullptr,
model,
preview_override))
continue;
if (simulation_settings) {
if (!build_simulated_texture_mapping_color_preview_model_for_state(model_volume,
triangles_per_type[state_id],
filament_id,
*simulation_settings,
model,
preview_override))
continue;
} else {
if (!build_texture_mapping_color_preview_model_for_state(model_volume,
triangles_per_type[state_id],
nullptr,
model,
preview_override))
continue;
}
} else {
if (!build_vertex_color_preview_model_for_state(model_volume,
triangles_per_type[state_id],
simulation_settings ? &*simulation_settings : nullptr,
model))
continue;
if (simulation_settings) {
if (!build_simulated_vertex_color_preview_model_for_state(model_volume,
triangles_per_type[state_id],
filament_id,
*simulation_settings,
model))
continue;
} else {
if (!build_vertex_color_preview_model_for_state(model_volume, triangles_per_type[state_id], nullptr, model))
continue;
}
}
}
@@ -3026,7 +3472,7 @@ void render_model_texture_preview_models(
const std::array<float, 2> &print_volume_z,
bool opaque)
{
if (models.empty() || colors.size() != models.size() || filament_ids.size() != models.size() || texture.get_id() == 0)
if (models.empty() || colors.size() != models.size() || filament_ids.size() != models.size())
return;
GLShaderProgram *shader = GUI::wxGetApp().get_shader("painted_texture_preview");
@@ -3104,7 +3550,7 @@ void render_model_texture_preview_model(
const std::array<float, 2> &print_volume_z,
bool opaque)
{
if (texture.get_id() == 0 || !GUI::GLModel::Geometry::has_tex_coord(model.get_geometry().format))
if (!GUI::GLModel::Geometry::has_tex_coord(model.get_geometry().format))
return;
GLShaderProgram *shader = GUI::wxGetApp().get_shader("painted_texture_preview");

View File

@@ -65,6 +65,13 @@ bool ensure_model_volume_texture_preview(const ModelVolume &model_volume,
bool texture_preview_simulation_is_pending();
void clear_texture_preview_simulation_cache();
bool texture_preview_simulation_enabled_for_filament(unsigned int filament_id,
size_t num_physical,
const TextureMappingManager *texture_mgr);
bool texture_preview_simulation_enabled_for_all_filaments(const std::vector<unsigned int> &filament_ids,
size_t num_physical,
const TextureMappingManager *texture_mgr);
size_t texture_preview_simulation_generation_signature();
size_t texture_preview_settings_signature(size_t num_physical, const TextureMappingManager *texture_mgr);