diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 8694a516a87..4d0f31020a6 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -4696,9 +4696,13 @@ bool ColorFacetsAnnotation::set_from_triangle_sampler(const ModelVolume } void ColorFacetsAnnotation::get_facet_triangles(const ModelVolume &mv, std::vector &facets) const +{ + this->get_facet_triangles(mv.mesh().its, facets); +} + +void ColorFacetsAnnotation::get_facet_triangles(const indexed_triangle_set &its, std::vector &facets) const { facets.clear(); - const indexed_triangle_set &its = mv.mesh().its; if (its.vertices.empty() || its.indices.empty()) return; diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 0530ee3ae6d..dac008986b7 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -893,6 +893,7 @@ public: const std::vector *resample_triangles = nullptr, const TextureMappingColorLeafResamplePredicate &resample_leaf = {}); void get_facet_triangles(const ModelVolume &mv, std::vector &facets) const; + void get_facet_triangles(const indexed_triangle_set &its, std::vector &facets) const; private: explicit ColorFacetsAnnotation() = default; diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 8a1b41c8b1c..39d2a2e40ba 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -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(); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp index d56a9c7866b..5025056abe3 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoPainterBase.cpp @@ -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(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, diff --git a/src/slic3r/GUI/MMUPaintedTexturePreview.cpp b/src/slic3r/GUI/MMUPaintedTexturePreview.cpp index 1034c9bb020..54da506b5f9 100644 --- a/src/slic3r/GUI/MMUPaintedTexturePreview.cpp +++ b/src/slic3r/GUI/MMUPaintedTexturePreview.cpp @@ -115,6 +115,21 @@ struct TexturePreviewSimulationCacheEntry std::future 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 ready_geometry; + std::future 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> &abandoned_texture_prev return *futures; } +std::unordered_map> &texture_preview_vertex_color_simulation_cache() +{ + static auto *cache = new std::unordered_map>(); + return *cache; +} + +std::vector> &abandoned_texture_preview_vertex_color_futures() +{ + static auto *futures = new std::vector>(); + 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 &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 &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 &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 &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 &vertex_colors_rgba, + const std::vector &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 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(); const Vec3f source_p1 = its.vertices[size_t(source_indices[1])].cast(); const Vec3f source_p2 = its.vertices[size_t(source_indices[2])].cast(); const std::array 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 &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 &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 &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 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 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 &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 &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(std::lround(safe_value * 1000000.f)))); + }; + + mix(state_triangles.size()); + for (const TriangleSelector::FacetStateTriangle &triangle : state_triangles) { + mix(std::hash{}(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 &state_triangles) +{ + size_t signature = 1469598103934665603ull; + auto mix = [&signature](size_t value) { + signature ^= value + 0x9e3779b97f4a7c15ull + (signature << 6) + (signature >> 2); + }; + + mix(reinterpret_cast(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(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 &state_triangles) +{ + size_t signature = 1469598103934665603ull; + auto mix = [&signature](size_t value) { + signature ^= value + 0x9e3779b97f4a7c15ull + (signature << 6) + (signature >> 2); + }; + + mix(reinterpret_cast(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(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{}(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 build_result, + GUI::GLModel &out_model) +{ + auto &cache = texture_preview_vertex_color_simulation_cache(); + std::shared_ptr &entry_ref = cache[cache_key]; + if (entry_ref == nullptr) + entry_ref = std::make_shared(); + 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 &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 mesh = model_volume.mesh_ptr(); + std::vector vertex_colors(model_volume.imported_vertex_colors_rgba.begin(), model_volume.imported_vertex_colors_rgba.end()); + std::vector 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 &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 mesh = model_volume.mesh_ptr(); + ColorFacetsAnnotation color_source_copy(*color_source); + std::vector 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 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 &filament_ids, + size_t num_physical, + const TextureMappingManager *texture_mgr) +{ + if (filament_ids.empty()) + return false; + + const std::vector 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> &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 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 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 &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 &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"); diff --git a/src/slic3r/GUI/MMUPaintedTexturePreview.hpp b/src/slic3r/GUI/MMUPaintedTexturePreview.hpp index c15677f4de9..8b05a1dd16c 100644 --- a/src/slic3r/GUI/MMUPaintedTexturePreview.hpp +++ b/src/slic3r/GUI/MMUPaintedTexturePreview.hpp @@ -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 &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);