From 1134d45530dd0ce6e1b57b0f1a3f98f0d42fb925 Mon Sep 17 00:00:00 2001 From: sentientstardust Date: Sun, 3 May 2026 13:12:14 +0100 Subject: [PATCH] Work on 3d preview. Fix 3mf texture loading --- src/libslic3r/Format/bbs_3mf.cpp | 94 +++++++- src/libslic3r/GCode/ToolOrdering.cpp | 27 ++- src/libslic3r/Model.hpp | 2 + src/slic3r/GUI/3DScene.cpp | 322 ++++++++++++++++++--------- src/slic3r/GUI/3DScene.hpp | 7 + src/slic3r/GUI/wxExtensions.cpp | 6 +- 6 files changed, 342 insertions(+), 116 deletions(-) diff --git a/src/libslic3r/Format/bbs_3mf.cpp b/src/libslic3r/Format/bbs_3mf.cpp index 72104c647a..8ad2a47bd1 100644 --- a/src/libslic3r/Format/bbs_3mf.cpp +++ b/src/libslic3r/Format/bbs_3mf.cpp @@ -755,6 +755,39 @@ struct PendingThreeMfImportedTexture std::vector uv_valid; }; +static bool build_single_texture_source_from_resources( + PendingThreeMfImportedTexture &out, + const size_t triangles_count, + const std::map &texture_groups, + const std::map &texture_resources) +{ + if (triangles_count == 0 || texture_groups.size() != 1) + return false; + + const ThreeMfTexture2DGroupResource &group = texture_groups.begin()->second; + const auto texture_it = texture_resources.find(group.tex_id); + if (texture_it == texture_resources.end() || texture_it->second.path.empty()) + return false; + if (group.coords.size() < triangles_count * 3) + return false; + + out.image_file = texture_it->second.path; + out.image_content_type = texture_it->second.content_type; + out.uv_valid.assign(triangles_count, uint8_t(1)); + out.uvs_per_face.resize(triangles_count * 6); + for (size_t triangle_idx = 0; triangle_idx < triangles_count; ++triangle_idx) { + const size_t coord_idx = triangle_idx * 3; + const size_t uv_idx = triangle_idx * 6; + out.uvs_per_face[uv_idx + 0] = group.coords[coord_idx + 0].first; + out.uvs_per_face[uv_idx + 1] = group.coords[coord_idx + 0].second; + out.uvs_per_face[uv_idx + 2] = group.coords[coord_idx + 1].first; + out.uvs_per_face[uv_idx + 3] = group.coords[coord_idx + 1].second; + out.uvs_per_face[uv_idx + 4] = group.coords[coord_idx + 2].first; + out.uvs_per_face[uv_idx + 5] = group.coords[coord_idx + 2].second; + } + return true; +} + struct ThreeMfExportTextureResource { int color_group_id{-1}; @@ -5799,18 +5832,26 @@ static void append_triangle_material_data(std::vector &uv_valid, m_volume_subobject_ids[volume] = sub_object->id; + PendingThreeMfImportedTexture texture_source; + bool has_texture_source = false; if (!sub_object->geometry.texture_image_path.empty() && !sub_object->geometry.texture_uses_multiple_images && sub_object->geometry.texture_uv_valid.size() == triangles_count && sub_object->geometry.texture_uvs_per_face.size() >= triangles_count * 6) { - PendingThreeMfImportedTexture texture_source; texture_source.image_file = sub_object->geometry.texture_image_path; texture_source.image_content_type = sub_object->geometry.texture_image_content_type; texture_source.uv_valid = sub_object->geometry.texture_uv_valid; texture_source.uvs_per_face.assign(sub_object->geometry.texture_uvs_per_face.begin(), sub_object->geometry.texture_uvs_per_face.begin() + triangles_count * 6); - m_standard_texture_sources[volume] = std::move(texture_source); + has_texture_source = true; + } else if (build_single_texture_source_from_resources(texture_source, + triangles_count, + m_texture_groups, + m_texture_resources)) { + has_texture_source = true; } + if (has_texture_source) + m_standard_texture_sources[volume] = std::move(texture_source); const size_t vertices_count = volume->mesh().its.vertices.size(); if (sub_object->geometry.vertex_colors_rgba.size() == vertices_count && @@ -5910,6 +5951,47 @@ static void append_triangle_material_data(std::vector &uv_valid, if (m_model == nullptr) return; + for (ModelObject *object : m_model->objects) { + if (object == nullptr) + continue; + for (ModelVolume *volume : object->volumes) { + if (volume == nullptr || m_standard_texture_sources.find(volume) != m_standard_texture_sources.end()) + continue; + const auto subobject_id = m_volume_subobject_ids.find(volume); + if (subobject_id == m_volume_subobject_ids.end()) + continue; + const size_t triangle_count = volume->mesh().its.indices.size(); + if (triangle_count == 0) + continue; + auto current_object = std::find_if(m_current_objects.begin(), m_current_objects.end(), [subobject_id, triangle_count](const auto &item) { + const Geometry &geometry = item.second.geometry; + return item.second.id == subobject_id->second && + !geometry.texture_image_path.empty() && + !geometry.texture_uses_multiple_images && + geometry.texture_uv_valid.size() >= triangle_count && + geometry.texture_uvs_per_face.size() >= triangle_count * 6; + }); + PendingThreeMfImportedTexture texture_source; + bool has_texture_source = false; + if (current_object != m_current_objects.end()) { + texture_source.image_file = current_object->second.geometry.texture_image_path; + texture_source.image_content_type = current_object->second.geometry.texture_image_content_type; + texture_source.uv_valid.assign(current_object->second.geometry.texture_uv_valid.begin(), + current_object->second.geometry.texture_uv_valid.begin() + triangle_count); + texture_source.uvs_per_face.assign(current_object->second.geometry.texture_uvs_per_face.begin(), + current_object->second.geometry.texture_uvs_per_face.begin() + triangle_count * 6); + has_texture_source = true; + } else if (build_single_texture_source_from_resources(texture_source, + triangle_count, + m_texture_groups, + m_texture_resources)) { + has_texture_source = true; + } + if (has_texture_source) + m_standard_texture_sources[volume] = std::move(texture_source); + } + } + for (auto &standard_texture_entry : m_standard_texture_sources) { ModelVolume *volume = standard_texture_entry.first; if (volume == nullptr) @@ -5939,17 +6021,21 @@ static void append_triangle_material_data(std::vector &uv_valid, } const size_t triangle_count = volume->mesh().its.indices.size(); - if (source.uv_valid.size() != triangle_count || source.uvs_per_face.size() < triangle_count * 6) { + if (source.uv_valid.size() < triangle_count || source.uvs_per_face.size() < triangle_count * 6) { BOOST_LOG_TRIVIAL(warning) << "3MF texture2d UV payload triangle mismatch for image='" << source.image_file << "'"; continue; } - volume->imported_texture_uv_valid = source.uv_valid; + volume->imported_texture_uv_valid.assign(source.uv_valid.begin(), + source.uv_valid.begin() + triangle_count); volume->imported_texture_uvs_per_face.assign(source.uvs_per_face.begin(), source.uvs_per_face.begin() + triangle_count * 6); volume->imported_texture_rgba = std::move(imported_rgba); volume->imported_texture_width = imported_width; volume->imported_texture_height = imported_height; + volume->imported_texture_uv_valid.set_new_unique_id(); + volume->imported_texture_uvs_per_face.set_new_unique_id(); + volume->imported_texture_rgba.set_new_unique_id(); } } /* diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index e81d49379c..de24838217 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -157,18 +157,33 @@ static double calc_max_layer_height(const PrintConfig &config, double max_object static FilamentChangeStats calc_filament_change_info_by_toolorder(const PrintConfig* config, const std::vector& filament_map, const std::vector& flush_matrix, const std::vector>& layer_sequences) { FilamentChangeStats ret; + if (config == nullptr || filament_map.empty() || flush_matrix.empty()) + return ret; + std::unordered_map flush_volume_per_filament; - int max_extruder_id = *std::max_element(filament_map.begin(), filament_map.end()); - assert(max_extruder_id >= 0); - std::vectorlast_filament_per_extruder(max_extruder_id + 1, -1); + int max_extruder_id = -1; + for (int extruder_id : filament_map) + max_extruder_id = std::max(max_extruder_id, extruder_id); + if (max_extruder_id < 0) + return ret; + const unsigned int invalid_filament_id = static_cast(-1); + std::vectorlast_filament_per_extruder(max_extruder_id + 1, invalid_filament_id); int total_filament_change_count = 0; float total_filament_flush_weight = 0; for (const auto& ls : layer_sequences) { for (const auto& item : ls) { + if (static_cast(item) >= filament_map.size()) + continue; int extruder_id = filament_map[item]; - int last_filament = last_filament_per_extruder[extruder_id]; - if (last_filament != -1 && last_filament != item) { + if (extruder_id < 0 || static_cast(extruder_id) >= last_filament_per_extruder.size()) + continue; + unsigned int last_filament = last_filament_per_extruder[extruder_id]; + if (last_filament != invalid_filament_id && last_filament != item) { + if (static_cast(extruder_id) >= flush_matrix.size() || + static_cast(last_filament) >= flush_matrix[extruder_id].size() || + static_cast(item) >= flush_matrix[extruder_id][last_filament].size()) + continue; int flush_volume = flush_matrix[extruder_id][last_filament][item]; flush_volume_per_filament[item] += flush_volume; total_filament_change_count += 1; @@ -178,6 +193,8 @@ static FilamentChangeStats calc_filament_change_info_by_toolorder(const PrintCon } for (auto& fv : flush_volume_per_filament) { + if (fv.first < 0 || static_cast(fv.first) >= config->filament_density.values.size()) + continue; float weight = config->filament_density.get_at(fv.first) * 0.001 * fv.second; total_filament_flush_weight += weight; } diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 472a3fed15..a0e72e41bb 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -945,6 +945,8 @@ public: return *this; } + void set_new_unique_id() { ObjectBase::set_new_unique_id(); } + private: explicit ModelVolumeImportedVector(int) : ObjectBase(-1) {} diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index a29ba8d3ba..c2b441b569 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -114,13 +114,29 @@ std::vector build_full_mesh_texture_previe return out; } -bool model_volume_has_any_texture_preview_data(const ModelVolume &model_volume) +const TextureMappingZone *texture_preview_zone_for_filament(unsigned int filament_id, + size_t num_physical, + const TextureMappingManager *texture_mgr) { - return !model_volume.texture_mapping_color_facets.empty() || - !model_volume.imported_vertex_colors_rgba.empty() || - (!model_volume.imported_texture_rgba.empty() && - model_volume.imported_texture_width > 0 && - model_volume.imported_texture_height > 0); + const TextureMappingZone *zone = texture_mgr != nullptr && filament_id > num_physical ? + texture_mgr->zone_from_id(filament_id) : nullptr; + return zone != nullptr && zone->enabled && !zone->deleted && (zone->is_image_texture() || zone->is_2d_gradient()) ? + zone : nullptr; +} + +bool filament_state_uses_texture_preview(unsigned int filament_id, + size_t num_physical, + const TextureMappingManager *texture_mgr) +{ + return texture_preview_zone_for_filament(filament_id, num_physical, texture_mgr) != nullptr; +} + +bool filament_state_uses_surface_gradient_preview(unsigned int filament_id, + size_t num_physical, + const TextureMappingManager *texture_mgr) +{ + const TextureMappingZone *zone = texture_preview_zone_for_filament(filament_id, num_physical, texture_mgr); + return zone != nullptr && zone->is_2d_gradient(); } bool texture_preview_has_surface_gradient_state(size_t states_count, @@ -128,13 +144,9 @@ bool texture_preview_has_surface_gradient_state(size_t states_count, size_t num_physical, const TextureMappingManager *texture_mgr) { - if (texture_mgr == nullptr) - return false; - for (size_t state_id = 0; state_id < states_count; ++state_id) { const unsigned int filament_id = state_id == 0 ? base_filament_id : unsigned(state_id); - const TextureMappingZone *zone = texture_mgr->zone_from_id(filament_id); - if (zone != nullptr && zone->enabled && !zone->deleted && zone->is_2d_gradient()) + if (filament_state_uses_surface_gradient_preview(filament_id, num_physical, texture_mgr)) return true; } @@ -646,32 +658,37 @@ void GLVolume::simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_obj const TextureMappingManager *texture_mgr = GUI::wxGetApp().preset_bundle != nullptr ? &GUI::wxGetApp().preset_bundle->texture_mapping_zones : nullptr; base_filament_id = model_volume->extruder_id() > 0 ? unsigned(model_volume->extruder_id()) : 0u; - const TextureMappingZone *base_zone = texture_mgr != nullptr ? texture_mgr->zone_from_id(base_filament_id) : nullptr; const bool has_mmu_segmentation = !model_volume->mmu_segmentation_facets.empty(); - const bool has_texture_mapping_color_preview_data = model_volume_has_texture_mapping_color_preview_data(*model_volume); + const bool base_uses_texture_preview = filament_state_uses_texture_preview(base_filament_id, num_physical, texture_mgr); + const bool base_uses_surface_gradient_preview = + filament_state_uses_surface_gradient_preview(base_filament_id, num_physical, texture_mgr); + const bool base_uses_image_texture_preview = base_uses_texture_preview && !base_uses_surface_gradient_preview; + const bool has_texture_mapping_color_preview_data = + base_uses_texture_preview && model_volume_has_texture_mapping_color_preview_data(*model_volume); const bool has_texture_preview_data = model_volume_has_texture_preview_data(*model_volume); - const bool has_texture_preview = - base_zone != nullptr && - base_zone->enabled && - !base_zone->deleted && - (base_zone->is_2d_gradient() || (base_zone->is_image_texture() && model_volume_has_any_texture_preview_data(*model_volume))); use_original_mesh_texture_preview = !has_mmu_segmentation && !has_texture_mapping_color_preview_data && - base_zone != nullptr && - base_zone->enabled && - !base_zone->deleted && - base_zone->is_image_texture() && + base_uses_image_texture_preview && model_volume_has_complete_texture_preview_data(*model_volume) && GUI::GLModel::Geometry::has_tex_coord(model.get_geometry().format); - if (!has_mmu_segmentation && !has_texture_preview) + if (!has_mmu_segmentation && !base_uses_texture_preview) { + mmuseg_models.clear(); + mmuseg_texture_preview_models.clear(); + mmuseg_texture_preview_colors.clear(); + mmuseg_texture_preview_filament_ids.clear(); + mmuseg_vertex_color_preview_models.clear(); + mmuseg_vertex_color_preview_colors.clear(); + mmuseg_vertex_color_preview_filament_ids.clear(); mmuseg_texture_preview.reset(); mmuseg_texture_preview_signature = 0; + mmuseg_texture_preview_visual_signature = 0; + mmuseg_ts = model_volume->mmu_segmentation_facets.timestamp(); break; } - color_volume = true; + color_volume = has_mmu_segmentation; size_t preview_visual_signature = texture_preview_settings_signature(num_physical, texture_mgr); preview_visual_signature ^= model_volume_texture_preview_signature(*model_volume) + 0x9e3779b97f4a7c15ull + (preview_visual_signature << 6) + (preview_visual_signature >> 2); @@ -692,12 +709,16 @@ void GLVolume::simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_obj mmuseg_vertex_color_preview_filament_ids.clear(); std::vector> triangles_per_type; + bool has_texture_preview_state = base_uses_texture_preview; if (has_mmu_segmentation) { std::vector its_per_color; model_volume->mmu_segmentation_facets.get_facets(*model_volume, its_per_color); mmuseg_models.resize(its_per_color.size()); for (int idx = 0; idx < its_per_color.size(); idx++) { mmuseg_models[idx].init_from(its_per_color[idx]); + if (!its_per_color[idx].indices.empty()) + has_texture_preview_state = has_texture_preview_state || + filament_state_uses_texture_preview(unsigned(idx), num_physical, texture_mgr); } model_volume->mmu_segmentation_facets.get_facet_triangles(*model_volume, triangles_per_type); } else { @@ -713,7 +734,9 @@ void GLVolume::simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_obj fallback_color); state_colors.insert(state_colors.end(), extruder_colors.begin(), extruder_colors.end()); - if (!use_original_mesh_texture_preview && !has_texture_mapping_color_preview_data && has_texture_preview_data) { + const bool has_active_texture_mapping_color_preview_data = + has_texture_preview_state && model_volume_has_texture_mapping_color_preview_data(*model_volume); + if (has_texture_preview_state && !use_original_mesh_texture_preview && !has_active_texture_mapping_color_preview_data && has_texture_preview_data) { build_mmu_texture_preview_models(*model_volume, triangles_per_type, state_colors, @@ -724,9 +747,10 @@ void GLVolume::simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_obj mmuseg_texture_preview_colors, mmuseg_texture_preview_filament_ids); } - if (has_texture_mapping_color_preview_data || + if (has_texture_preview_state && + (has_active_texture_mapping_color_preview_data || !has_texture_preview_data || - texture_preview_has_surface_gradient_state(triangles_per_type.size(), base_filament_id, num_physical, texture_mgr)) { + texture_preview_has_surface_gradient_state(triangles_per_type.size(), base_filament_id, num_physical, texture_mgr))) { build_mmu_vertex_color_preview_models(*model_volume, triangles_per_type, state_colors, @@ -795,76 +819,6 @@ void GLVolume::simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_obj m.render(this->tverts_range, shader); } } - - if (use_original_mesh_texture_preview || !mmuseg_texture_preview_models.empty() || !mmuseg_vertex_color_preview_models.empty()) { - auto adjusted_preview_colors = [](const std::vector &colors) { - std::vector preview_colors = colors; - for (ColorRGBA &preview_color : preview_colors) - preview_color = adjust_color_for_rendering(preview_color); - return preview_colors; - }; - const size_t num_physical = std::max(0, GUI::wxGetApp().filaments_cnt()); - const TextureMappingManager *texture_mgr = GUI::wxGetApp().preset_bundle != nullptr ? - &GUI::wxGetApp().preset_bundle->texture_mapping_zones : nullptr; - const Transform3d model_matrix = this->world_matrix(); - const GUI::Camera& camera = GUI::wxGetApp().plater()->get_camera(); - const std::array z_range = { -std::numeric_limits::max(), std::numeric_limits::max() }; - const std::array clipping_plane = { 0.f, 0.f, 1.f, std::numeric_limits::max() }; - - 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)) { - 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(); - ColorRGBA original_mesh_preview_color = extruder_id > 0 && size_t(extruder_id - 1) < extruder_colors.size() ? - extruder_colors[size_t(extruder_id - 1)] : - fallback_color; - original_mesh_preview_color = adjust_color_for_rendering(original_mesh_preview_color); - if (force_native_color && render_color.is_transparent()) - original_mesh_preview_color.a(render_color.a()); - render_model_texture_preview_model(model, - original_mesh_preview_color, - base_filament_id, - num_physical, - texture_mgr, - *model_volume, - mmuseg_texture_preview, - model_matrix, - camera.get_view_matrix(), - camera.get_projection_matrix(), - z_range, - clipping_plane, - this->tverts_range); - } else { - render_model_texture_preview_models(mmuseg_texture_preview_models, - adjusted_preview_colors(mmuseg_texture_preview_colors), - mmuseg_texture_preview_filament_ids, - num_physical, - texture_mgr, - *model_volume, - mmuseg_texture_preview, - model_matrix, - camera.get_view_matrix(), - camera.get_projection_matrix(), - z_range, - clipping_plane); - } - } - if (!mmuseg_vertex_color_preview_models.empty()) { - render_model_vertex_color_preview_models(mmuseg_vertex_color_preview_models, - adjusted_preview_colors(mmuseg_vertex_color_preview_colors), - mmuseg_vertex_color_preview_filament_ids, - num_physical, - texture_mgr, - model_matrix, - camera.get_view_matrix(), - camera.get_projection_matrix(), - z_range, - clipping_plane); - } - if (shader != nullptr) - shader->start_using(); - } } else { if (tverts_range == std::make_pair(0, -1)) model.render(shader); @@ -875,6 +829,137 @@ void GLVolume::simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_obj glFrontFace(GL_CCW); } +void GLVolume::render_mmu_texture_preview(const Transform3d &view_matrix, + const Transform3d &projection_matrix, + const std::array &z_range, + const std::array &clipping_plane, + int print_volume_type, + const std::array &print_volume_xy, + const std::array &print_volume_z) +{ + if (picking || !printable || object_idx() < 0 || volume_idx() < 0) + return; + + ModelObjectPtrs &model_objects = GUI::wxGetApp().model().objects; + if (size_t(object_idx()) >= model_objects.size()) + return; + + const ModelObject *model_object = model_objects[size_t(object_idx())]; + if (model_object == nullptr || size_t(volume_idx()) >= model_object->volumes.size()) + return; + + const ModelVolume *model_volume = model_object->volumes[size_t(volume_idx())]; + if (model_volume == nullptr) + return; + + const size_t num_physical = std::max(0, GUI::wxGetApp().filaments_cnt()); + const TextureMappingManager *texture_mgr = GUI::wxGetApp().preset_bundle != nullptr ? + &GUI::wxGetApp().preset_bundle->texture_mapping_zones : nullptr; + const unsigned int base_filament_id = model_volume->extruder_id() > 0 ? unsigned(model_volume->extruder_id()) : 0u; + const bool base_uses_texture_preview = filament_state_uses_texture_preview(base_filament_id, num_physical, texture_mgr); + const bool base_uses_surface_gradient_preview = + filament_state_uses_surface_gradient_preview(base_filament_id, num_physical, texture_mgr); + const bool base_uses_image_texture_preview = base_uses_texture_preview && !base_uses_surface_gradient_preview; + + const bool has_mmu_segmentation = !model_volume->mmu_segmentation_facets.empty(); + const bool has_texture_mapping_color_preview_data = model_volume_has_texture_mapping_color_preview_data(*model_volume); + const bool use_original_mesh_texture_preview = + !has_mmu_segmentation && + !has_texture_mapping_color_preview_data && + base_uses_image_texture_preview && + model_volume_has_complete_texture_preview_data(*model_volume) && + GUI::GLModel::Geometry::has_tex_coord(model.get_geometry().format); + + if (!use_original_mesh_texture_preview && mmuseg_texture_preview_models.empty()) { + mmuseg_texture_preview.reset(); + mmuseg_texture_preview_signature = 0; + } + + if (!use_original_mesh_texture_preview && mmuseg_texture_preview_models.empty() && mmuseg_vertex_color_preview_models.empty()) + return; + + if (this->is_left_handed()) + glFrontFace(GL_CW); + glsafe(::glCullFace(GL_BACK)); + + const Transform3d model_matrix = this->world_matrix(); + const std::vector extruder_colors = GUI::wxGetApp().plater()->get_extruders_colors(); + auto adjusted_preview_colors = [this](const std::vector &colors) { + std::vector preview_colors = colors; + for (ColorRGBA &preview_color : preview_colors) { + preview_color = adjust_color_for_rendering(preview_color); + if (force_native_color && render_color.is_transparent()) + preview_color.a(render_color.a()); + } + return preview_colors; + }; + + 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)) { + 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(); + ColorRGBA original_mesh_preview_color = extruder_id > 0 && size_t(extruder_id - 1) < extruder_colors.size() ? + extruder_colors[size_t(extruder_id - 1)] : + fallback_color; + original_mesh_preview_color = adjust_color_for_rendering(original_mesh_preview_color); + if (force_native_color && render_color.is_transparent()) + original_mesh_preview_color.a(render_color.a()); + render_model_texture_preview_model(model, + original_mesh_preview_color, + base_filament_id, + num_physical, + texture_mgr, + *model_volume, + mmuseg_texture_preview, + model_matrix, + view_matrix, + projection_matrix, + z_range, + clipping_plane, + this->tverts_range, + print_volume_type, + print_volume_xy, + print_volume_z); + } else { + render_model_texture_preview_models(mmuseg_texture_preview_models, + adjusted_preview_colors(mmuseg_texture_preview_colors), + mmuseg_texture_preview_filament_ids, + num_physical, + texture_mgr, + *model_volume, + mmuseg_texture_preview, + model_matrix, + view_matrix, + projection_matrix, + z_range, + clipping_plane, + print_volume_type, + print_volume_xy, + print_volume_z); + } + } + + if (!mmuseg_vertex_color_preview_models.empty()) { + render_model_vertex_color_preview_models(mmuseg_vertex_color_preview_models, + adjusted_preview_colors(mmuseg_vertex_color_preview_colors), + mmuseg_vertex_color_preview_filament_ids, + num_physical, + texture_mgr, + model_matrix, + view_matrix, + projection_matrix, + z_range, + clipping_plane, + print_volume_type, + print_volume_xy, + print_volume_z); + } + + if (this->is_left_handed()) + glFrontFace(GL_CCW); +} + void GLVolume::invalidate_texture_mapping_preview() { mmuseg_models.clear(); @@ -1760,10 +1845,23 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, else volume.first->render(); + const int texture_preview_print_volume_type = + volume.first->partly_inside && partly_inside_enable ? static_cast(m_print_volume.type) : -1; + const std::array texture_preview_clipping_plane = { + float(m_clipping_plane[0]), + float(m_clipping_plane[1]), + float(m_clipping_plane[2]), + float(m_clipping_plane[3]) + }; + shader->stop_using(); + volume.first->render_mmu_texture_preview(view_matrix, + projection_matrix, + m_z_range, + texture_preview_clipping_plane, + texture_preview_print_volume_type, + m_print_volume.data, + m_print_volume.zs); if (GLWipeTowerVolume *wipe_tower_volume = dynamic_cast(volume.first)) { - const int texture_preview_print_volume_type = - volume.first->partly_inside && partly_inside_enable ? static_cast(m_print_volume.type) : -1; - shader->stop_using(); wipe_tower_volume->render_prime_tower_image_preview(view_matrix, projection_matrix, m_z_range, @@ -1771,8 +1869,8 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, texture_preview_print_volume_type, m_print_volume.data, m_print_volume.zs); - shader->start_using(); } + shader->start_using(); #if ENABLE_ENVIRONMENT_MAP if (use_environment_texture) @@ -2153,14 +2251,26 @@ void GLVolumeCollection::update_colors_by_extruder(const DynamicPrintConfig *con if (filamemts_opt == nullptr) return; - size_t colors_count = (size_t)filamemts_opt->values.size(); - if (colors_count == 0) + std::vector filament_colors = filamemts_opt->values; + if (filament_colors.empty()) return; - colors.resize(colors_count); - for (unsigned int i = 0; i < colors_count; ++i) { + if (GUI::wxGetApp().preset_bundle != nullptr) { + const size_t physical_count = filament_colors.size(); + const TextureMappingManager &texture_mgr = GUI::wxGetApp().preset_bundle->texture_mapping_zones; + const size_t total_count = texture_mgr.total_filaments(physical_count); + filament_colors.resize(total_count, "#8C8C8C"); + for (const TextureMappingZone &zone : texture_mgr.zones()) { + if (zone.enabled && !zone.deleted && zone.zone_id >= 1 && zone.zone_id <= filament_colors.size() && !zone.display_color.empty()) + filament_colors[zone.zone_id - 1] = zone.display_color; + } + } + + colors.resize(filament_colors.size()); + + for (size_t i = 0; i < filament_colors.size(); ++i) { ColorRGBA rgba; - const std::string& fil_color = config->opt_string("filament_colour", i); + const std::string& fil_color = filament_colors[i]; if (decode_color(fil_color, rgba)) colors[i] = { fil_color, rgba }; } diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index aa92ad3ed2..d49fecee2b 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -359,6 +359,13 @@ public: //BBS: add simple render function for thumbnail void simple_render(GLShaderProgram* shader, ModelObjectPtrs& model_objects, std::vector& extruder_colors, bool ban_light =false); + void render_mmu_texture_preview(const Transform3d &view_matrix, + const Transform3d &projection_matrix, + const std::array &z_range, + const std::array &clipping_plane, + int print_volume_type = -1, + const std::array &print_volume_xy = std::array{ 0.f, 0.f, 0.f, 0.f }, + const std::array &print_volume_z = std::array{ 0.f, 0.f }); void invalidate_texture_mapping_preview(); void set_bounding_boxes_as_dirty() { diff --git a/src/slic3r/GUI/wxExtensions.cpp b/src/slic3r/GUI/wxExtensions.cpp index 9e096f1399..d2302d46cb 100644 --- a/src/slic3r/GUI/wxExtensions.cpp +++ b/src/slic3r/GUI/wxExtensions.cpp @@ -562,6 +562,11 @@ std::vector get_extruder_color_icons(bool thin_icon/* = false*/) bmps.push_back(get_extruder_color_icon(colors, is_gradient, label, icon_width, icon_height)); } } + const std::vector display_colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); + for (size_t idx = bmps.size(); idx < display_colors.size(); ++idx) { + const std::string label = std::to_string(idx + 1); + bmps.push_back(get_extruder_color_icon(display_colors[idx], label, icon_width, icon_height)); + } } else { std::vector colors = Slic3r::GUI::wxGetApp().plater()->get_extruder_colors_from_plater_config(); if (colors.empty()) return bmps; @@ -1259,4 +1264,3 @@ void ImageTransientPopup::OnMouse(wxMouseEvent &event) } -