diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index e7b35490fe..2c8dc3b2b4 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -2043,35 +2043,46 @@ void ModelInstance::transform_polygon(Polygon* polygon) const polygon->scale(get_scaling_factor(X), get_scaling_factor(Y)); // scale around polygon origin } -indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, TriangleStateType type) const -{ +indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume &mv, TriangleStateType type) const { TriangleSelector selector(mv.mesh()); // Reset of TriangleSelector is done inside TriangleSelector's constructor, so we don't need it to perform it again in deserialize(). selector.deserialize(m_data, false); return selector.get_facets(type); } -indexed_triangle_set FacetsAnnotation::get_facets_strict(const ModelVolume& mv, TriangleStateType type) const -{ +indexed_triangle_set FacetsAnnotation::get_facets_strict(const ModelVolume &mv, TriangleStateType type) const { TriangleSelector selector(mv.mesh()); // Reset of TriangleSelector is done inside TriangleSelector's constructor, so we don't need it to perform it again in deserialize(). selector.deserialize(m_data, false); return selector.get_facets_strict(type); } -bool FacetsAnnotation::has_facets(const ModelVolume& mv, TriangleStateType type) const -{ +indexed_triangle_set_with_color FacetsAnnotation::get_all_facets_with_colors(const ModelVolume &mv) const { + TriangleSelector selector(mv.mesh()); + // Reset of TriangleSelector is done inside TriangleSelector's constructor, so we don't need it to perform it again in deserialize(). + selector.deserialize(m_data, false); + return selector.get_all_facets_with_colors(); +} + +indexed_triangle_set_with_color FacetsAnnotation::get_all_facets_strict_with_colors(const ModelVolume &mv) const { + TriangleSelector selector(mv.mesh()); + // Reset of TriangleSelector is done inside TriangleSelector's constructor, so we don't need it to perform it again in deserialize(). + selector.deserialize(m_data, false); + return selector.get_all_facets_strict_with_colors(); +} + +bool FacetsAnnotation::has_facets(const ModelVolume &mv, TriangleStateType type) const { return TriangleSelector::has_facets(m_data, type); } -bool FacetsAnnotation::set(const TriangleSelector& selector) -{ +bool FacetsAnnotation::set(const TriangleSelector &selector) { TriangleSelector::TriangleSplittingData sel_map = selector.serialize(); if (sel_map != m_data) { m_data = std::move(sel_map); this->touch(); return true; } + return false; } diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 45431e65f3..820617f6a9 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -667,10 +667,12 @@ public: void assign(const FacetsAnnotation &rhs) { if (! this->timestamp_matches(rhs)) { m_data = rhs.m_data; this->copy_timestamp(rhs); } } void assign(FacetsAnnotation &&rhs) { if (! this->timestamp_matches(rhs)) { m_data = std::move(rhs.m_data); this->copy_timestamp(rhs); } } const TriangleSelector::TriangleSplittingData &get_data() const noexcept { return m_data; } - bool set(const TriangleSelector& selector); - indexed_triangle_set get_facets(const ModelVolume& mv, TriangleStateType type) const; - indexed_triangle_set get_facets_strict(const ModelVolume& mv, TriangleStateType type) const; - bool has_facets(const ModelVolume& mv, TriangleStateType type) const; + bool set(const TriangleSelector &selector); + indexed_triangle_set get_facets(const ModelVolume &mv, TriangleStateType type) const; + indexed_triangle_set get_facets_strict(const ModelVolume &mv, TriangleStateType type) const; + indexed_triangle_set_with_color get_all_facets_with_colors(const ModelVolume &mv) const; + indexed_triangle_set_with_color get_all_facets_strict_with_colors(const ModelVolume &mv) const; + bool has_facets(const ModelVolume &mv, TriangleStateType type) const; bool empty() const { return m_data.triangles_to_split.empty(); } // Following method clears the config and increases its timestamp, so the deleted diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index 9d46a79210..75bb095bf3 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -39,6 +39,30 @@ namespace Slic3r { class TriangleMesh; class TriangleMeshSlicer; +struct indexed_triangle_set_with_color +{ + std::vector indices; + std::vector vertices; + std::vector colors; +}; + +enum class AdditionalMeshInfo { + None, + Color +}; + +template struct IndexedTriangleSetType; + +template<> struct IndexedTriangleSetType +{ + using type = indexed_triangle_set; +}; + +template<> struct IndexedTriangleSetType +{ + using type = indexed_triangle_set_with_color; +}; + struct RepairedMeshErrors { // How many edges were united by merging their end points with some other end points in epsilon neighborhood? int edges_fixed = 0; @@ -394,7 +418,7 @@ inline BoundingBoxf3 bounding_box(const indexed_triangle_set& its, const Transfo return {bmin.cast(), bmax.cast()}; } -} +} // namespace Slic3r // Serialization through the Cereal library #include diff --git a/src/libslic3r/TriangleSelector.cpp b/src/libslic3r/TriangleSelector.cpp index bd33cbc2fd..3b951cf038 100644 --- a/src/libslic3r/TriangleSelector.cpp +++ b/src/libslic3r/TriangleSelector.cpp @@ -1333,13 +1333,16 @@ int TriangleSelector::num_facets(TriangleStateType state) const { return cnt; } -indexed_triangle_set TriangleSelector::get_facets(TriangleStateType state) const { - indexed_triangle_set out; +template +typename IndexedTriangleSetType::type TriangleSelector::get_facets(const std::function &facet_filter) const { + using IndexedTriangleSetType = typename IndexedTriangleSetType::type; + + IndexedTriangleSetType out; std::vector vertex_map(m_vertices.size(), -1); - for (const Triangle& tr : m_triangles) { - if (tr.valid() && ! tr.is_split() && tr.get_state() == state) { + for (const Triangle &tr : m_triangles) { + if (tr.valid() && !tr.is_split() && facet_filter(tr)) { stl_triangle_vertex_indices indices; - for (int i=0; i<3; ++i) { + for (int i = 0; i < 3; ++i) { int j = tr.verts_idxs[i]; if (vertex_map[j] == -1) { vertex_map[j] = int(out.vertices.size()); @@ -1348,55 +1351,105 @@ indexed_triangle_set TriangleSelector::get_facets(TriangleStateType state) const indices[i] = vertex_map[j]; } out.indices.emplace_back(indices); + + if constexpr (facet_info == AdditionalMeshInfo::Color) { + out.colors.emplace_back(static_cast(tr.get_state())); + } } } + return out; } -indexed_triangle_set TriangleSelector::get_facets_strict(TriangleStateType state) const { - indexed_triangle_set out; +indexed_triangle_set TriangleSelector::get_facets(TriangleStateType state) const { + return this->get_facets([state](const Triangle &tr) { return tr.get_state() == state; }); +} + +indexed_triangle_set TriangleSelector::get_all_facets() const { + return this->get_facets([](const Triangle &tr) { return true; }); +} + +indexed_triangle_set_with_color TriangleSelector::get_all_facets_with_colors() const { + return this->get_facets([](const Triangle &tr) { return true; }); +} + +template +typename IndexedTriangleSetType::type TriangleSelector::get_facets_strict(const std::function &facet_filter) const { + using IndexedTriangleSetType = typename IndexedTriangleSetType::type; + + auto get_vertices_count = [&vertices = std::as_const(m_vertices)]() -> size_t { + size_t vertices_cnt = 0; + for (const Vertex &v : vertices) { + if (v.ref_cnt > 0) + ++vertices_cnt; + } + + return vertices_cnt; + }; + + IndexedTriangleSetType out; + out.vertices.reserve(get_vertices_count()); - size_t num_vertices = 0; - for (const Vertex &v : m_vertices) - if (v.ref_cnt > 0) - ++ num_vertices; - out.vertices.reserve(num_vertices); std::vector vertex_map(m_vertices.size(), -1); - for (size_t i = 0; i < m_vertices.size(); ++ i) + for (size_t i = 0; i < m_vertices.size(); ++i) { if (const Vertex &v = m_vertices[i]; v.ref_cnt > 0) { vertex_map[i] = int(out.vertices.size()); out.vertices.emplace_back(v.v); } + } + std::vector out_colors; for (int itriangle = 0; itriangle < m_orig_size_indices; ++ itriangle) - this->get_facets_strict_recursive(m_triangles[itriangle], m_neighbors[itriangle], state, out.indices); + this->get_facets_strict_recursive(m_triangles[itriangle], m_neighbors[itriangle], facet_filter, out.indices, out_colors); - for (auto &triangle : out.indices) - for (int i = 0; i < 3; ++ i) + if constexpr (facet_info == AdditionalMeshInfo::Color) { + out.colors = std::move(out_colors); + } + + for (auto &triangle : out.indices) { + for (int i = 0; i < 3; ++i) { triangle(i) = vertex_map[triangle(i)]; + } + } return out; } +indexed_triangle_set TriangleSelector::get_facets_strict(TriangleStateType state) const { + return this->get_facets_strict([state](const Triangle &tr) { return tr.get_state() == state; }); +} + +indexed_triangle_set TriangleSelector::get_all_facets_strict() const { + return this->get_facets_strict([](const Triangle &tr) { return true; }); +} + +indexed_triangle_set_with_color TriangleSelector::get_all_facets_strict_with_colors() const { + return this->get_facets_strict([](const Triangle &tr) { return true; }); +} + +template void TriangleSelector::get_facets_strict_recursive( const Triangle &tr, const Vec3i &neighbors, - TriangleStateType state, - std::vector &out_triangles) const + const std::function &facet_filter, + std::vector &out_triangles, + std::vector &out_colors) const { if (tr.is_split()) { for (int i = 0; i <= tr.number_of_split_sides(); ++ i) - this->get_facets_strict_recursive( + this->get_facets_strict_recursive( m_triangles[tr.children[i]], this->child_neighbors(tr, neighbors, i), - state, out_triangles); - } else if (tr.get_state() == state) - this->get_facets_split_by_tjoints({tr.verts_idxs[0], tr.verts_idxs[1], tr.verts_idxs[2]}, neighbors, out_triangles); + facet_filter, out_triangles, out_colors); + } else if (facet_filter(tr)) { + const uint8_t facet_color = static_cast(tr.get_state()); + this->get_facets_split_by_tjoints({tr.verts_idxs[0], tr.verts_idxs[1], tr.verts_idxs[2]}, neighbors, facet_color, out_triangles, out_colors); + } } -void TriangleSelector::get_facets_split_by_tjoints(const Vec3i &vertices, const Vec3i &neighbors, std::vector &out_triangles) const -{ -// Export this triangle, but first collect the T-joint vertices along its edges. +template +void TriangleSelector::get_facets_split_by_tjoints(const Vec3i &vertices, const Vec3i &neighbors, const uint8_t color, std::vector &out_triangles, std::vector &out_colors) const { + // Export this triangle, but first collect the T-joint vertices along its edges. Vec3i midpoints( this->triangle_midpoint(neighbors(0), vertices(1), vertices(0)), this->triangle_midpoint(neighbors(1), vertices(2), vertices(1)), @@ -1406,6 +1459,11 @@ void TriangleSelector::get_facets_split_by_tjoints(const Vec3i &vertices, const case 0: // Just emit this triangle. out_triangles.emplace_back(vertices(0), vertices(1), vertices(2)); + + if constexpr (facet_info == AdditionalMeshInfo::Color) { + out_colors.emplace_back(color); + } + break; case 1: { @@ -1413,18 +1471,18 @@ void TriangleSelector::get_facets_split_by_tjoints(const Vec3i &vertices, const int i = midpoints(0) != -1 ? 2 : midpoints(1) != -1 ? 0 : 1; int j = next_idx_modulo(i, 3); int k = next_idx_modulo(j, 3); - this->get_facets_split_by_tjoints( + this->get_facets_split_by_tjoints( { vertices(i), vertices(j), midpoints(j) }, { neighbors(i), this->neighbor_child(neighbors(j), vertices(k), vertices(j), Partition::Second), -1 }, - out_triangles); - this->get_facets_split_by_tjoints( + color, out_triangles, out_colors); + this->get_facets_split_by_tjoints( { midpoints(j), vertices(k), vertices(i) }, { this->neighbor_child(neighbors(j), vertices(k), vertices(j), Partition::First), neighbors(k), -1 }, - out_triangles); + color, out_triangles, out_colors); break; } case 2: @@ -1433,47 +1491,53 @@ void TriangleSelector::get_facets_split_by_tjoints(const Vec3i &vertices, const int i = midpoints(0) == -1 ? 2 : midpoints(1) == -1 ? 0 : 1; int j = next_idx_modulo(i, 3); int k = next_idx_modulo(j, 3); - this->get_facets_split_by_tjoints( + this->get_facets_split_by_tjoints( { vertices(i), midpoints(i), midpoints(k) }, { this->neighbor_child(neighbors(i), vertices(j), vertices(i), Partition::Second), -1, this->neighbor_child(neighbors(k), vertices(i), vertices(k), Partition::First) }, - out_triangles); - this->get_facets_split_by_tjoints( + color, out_triangles, out_colors); + this->get_facets_split_by_tjoints( { midpoints(i), vertices(j), midpoints(k) }, { this->neighbor_child(neighbors(i), vertices(j), vertices(i), Partition::First), -1, -1 }, - out_triangles); - this->get_facets_split_by_tjoints( + color, out_triangles, out_colors); + this->get_facets_split_by_tjoints( { vertices(j), vertices(k), midpoints(k) }, { neighbors(j), this->neighbor_child(neighbors(k), vertices(i), vertices(k), Partition::Second), -1 }, - out_triangles); + color, out_triangles, out_colors); break; } default: assert(splits == 3); // Split to 4 triangles. - this->get_facets_split_by_tjoints( + this->get_facets_split_by_tjoints( { vertices(0), midpoints(0), midpoints(2) }, { this->neighbor_child(neighbors(0), vertices(1), vertices(0), Partition::Second), -1, this->neighbor_child(neighbors(2), vertices(0), vertices(2), Partition::First) }, - out_triangles); - this->get_facets_split_by_tjoints( + color, out_triangles, out_colors); + this->get_facets_split_by_tjoints( { midpoints(0), vertices(1), midpoints(1) }, { this->neighbor_child(neighbors(0), vertices(1), vertices(0), Partition::First), this->neighbor_child(neighbors(1), vertices(2), vertices(1), Partition::Second), -1 }, - out_triangles); - this->get_facets_split_by_tjoints( + color, out_triangles, out_colors); + this->get_facets_split_by_tjoints( { midpoints(1), vertices(2), midpoints(2) }, { this->neighbor_child(neighbors(1), vertices(2), vertices(1), Partition::First), this->neighbor_child(neighbors(2), vertices(0), vertices(2), Partition::Second), -1 }, - out_triangles); + color, out_triangles, out_colors); + out_triangles.emplace_back(midpoints); + + if constexpr (facet_info == AdditionalMeshInfo::Color) { + out_colors.emplace_back(color); + } + break; } } diff --git a/src/libslic3r/TriangleSelector.hpp b/src/libslic3r/TriangleSelector.hpp index 778c89f52b..0deb6aea52 100644 --- a/src/libslic3r/TriangleSelector.hpp +++ b/src/libslic3r/TriangleSelector.hpp @@ -313,10 +313,26 @@ public: bool has_facets(TriangleStateType state) const; static bool has_facets(const TriangleSplittingData &data, TriangleStateType test_state); int num_facets(TriangleStateType state) const; + // Get facets that pass the filter. Don't triangulate T-joints. + template + typename IndexedTriangleSetType::type get_facets(const std::function &facet_filter) const; // Get facets at a given state. Don't triangulate T-joints. indexed_triangle_set get_facets(TriangleStateType state) const; + // Get all facets. Don't triangulate T-joints. + indexed_triangle_set get_all_facets() const; + // Get all facets with information about the colors of the facets. Don't triangulate T-joints. + indexed_triangle_set_with_color get_all_facets_with_colors() const; + + // Get facets that pass the filter. Triangulate T-joints. + template + typename IndexedTriangleSetType::type get_facets_strict(const std::function &facet_filter) const; // Get facets at a given state. Triangulate T-joints. indexed_triangle_set get_facets_strict(TriangleStateType state) const; + // Get all facets. Triangulate T-joints. + indexed_triangle_set get_all_facets_strict() const; + // Get all facets with information about the colord of the facetd. Triangulate T-joints. + indexed_triangle_set_with_color get_all_facets_strict_with_colors() const; + // Get edges around the selected area by seed fill. std::vector get_seed_fill_contour() const; @@ -470,12 +486,16 @@ private: bool verify_triangle_midpoints(const Triangle& tr) const; #endif // NDEBUG + template void get_facets_strict_recursive( const Triangle &tr, const Vec3i &neighbors, - TriangleStateType state, - std::vector &out_triangles) const; - void get_facets_split_by_tjoints(const Vec3i &vertices, const Vec3i &neighbors, std::vector &out_triangles) const; + const std::function &facet_filter, + std::vector &out_triangles, + std::vector &out_colors) const; + + template + void get_facets_split_by_tjoints(const Vec3i &vertices, const Vec3i &neighbors, uint8_t color, std::vector &out_triangles, std::vector &out_colors) const; void get_seed_fill_contour_recursive(int facet_idx, const Vec3i &neighbors, const Vec3i &neighbors_propagated, std::vector &edges_out) const;