diff --git a/sandboxes/its_neighbor_index/ItsNeighborIndex.cpp b/sandboxes/its_neighbor_index/ItsNeighborIndex.cpp index 1d999d8cb8..92c0f57c33 100644 --- a/sandboxes/its_neighbor_index/ItsNeighborIndex.cpp +++ b/sandboxes/its_neighbor_index/ItsNeighborIndex.cpp @@ -4,6 +4,8 @@ #include #include "ItsNeighborIndex.hpp" +#include "libslic3r/Execution/ExecutionTBB.hpp" +#include "libslic3r/Execution/ExecutionSeq.hpp" #include "tbb/parallel_sort.h" @@ -343,20 +345,20 @@ std::vector> create_vertex_faces_index(const indexed_triangl return index; } -static int get_vertex_index(size_t vertex_index, const stl_triangle_vertex_indices &triangle_indices) { - if (vertex_index == triangle_indices[0]) return 0; - if (vertex_index == triangle_indices[1]) return 1; - if (vertex_index == triangle_indices[2]) return 2; - return -1; -} +//static int get_vertex_index(size_t vertex_index, const stl_triangle_vertex_indices &triangle_indices) { +// if (vertex_index == triangle_indices[0]) return 0; +// if (vertex_index == triangle_indices[1]) return 1; +// if (vertex_index == triangle_indices[2]) return 2; +// return -1; +//} -static Vec2crd get_edge_indices(int edge_index, const stl_triangle_vertex_indices &triangle_indices) -{ - int next_edge_index = (edge_index == 2) ? 0 : edge_index + 1; - coord_t vi0 = triangle_indices[edge_index]; - coord_t vi1 = triangle_indices[next_edge_index]; - return Vec2crd(vi0, vi1); -} +//static Vec2crd get_edge_indices(int edge_index, const stl_triangle_vertex_indices &triangle_indices) +//{ +// int next_edge_index = (edge_index == 2) ? 0 : edge_index + 1; +// coord_t vi0 = triangle_indices[edge_index]; +// coord_t vi1 = triangle_indices[next_edge_index]; +// return Vec2crd(vi0, vi1); +//} static std::vector> create_vertex_faces_index( const std::vector& indices, size_t count_vertices) @@ -600,42 +602,12 @@ FaceNeighborIndex its_create_neighbors_index_8(const indexed_triangle_set &its) std::vector its_create_neighbors_index_9(const indexed_triangle_set &its) { - const std::vector &indices = its.indices; - size_t vertices_size = its.vertices.size(); + return create_neighbors_index(ex_seq, its); +} - if (indices.empty() || vertices_size == 0) return {}; - // std::vector> vertex_triangles = create_vertex_faces_index(indices, vertices_size); - auto vertex_triangles = VertexFaceIndex{its}; - coord_t no_value = -1; - std::vector neighbors(indices.size(), Vec3crd(no_value, no_value, no_value)); - for (const stl_triangle_vertex_indices& triangle_indices : indices) { - coord_t index = &triangle_indices - &indices.front(); - Vec3crd& neighbor = neighbors[index]; - for (int edge_index = 0; edge_index < 3; ++edge_index) { - // check if done - coord_t& neighbor_edge = neighbor[edge_index]; - if (neighbor_edge != no_value) continue; - Vec2crd edge_indices = get_edge_indices(edge_index, triangle_indices); - // IMPROVE: use same vector for 2 sides of triangle - const auto &faces_range = vertex_triangles[edge_indices[0]]; - for (const size_t &face : faces_range) { - if (face <= index) continue; - const stl_triangle_vertex_indices &face_indices = indices[face]; - int vertex_index = get_vertex_index(edge_indices[1], face_indices); - // NOT Contain second vertex? - if (vertex_index < 0) continue; - // Has NOT oposit direction? - if (edge_indices[0] != face_indices[(vertex_index + 1) % 3]) continue; - neighbor_edge = face; - neighbors[face][vertex_index] = index; - break; - } - // must be paired - assert(neighbor_edge != no_value); - } - } - - return neighbors; +std::vector its_create_neighbors_index_10(const indexed_triangle_set &its) +{ + return create_neighbors_index(ex_tbb, its); } } // namespace Slic3r diff --git a/sandboxes/its_neighbor_index/ItsNeighborIndex.hpp b/sandboxes/its_neighbor_index/ItsNeighborIndex.hpp index 37452c10ae..66f2b23485 100644 --- a/sandboxes/its_neighbor_index/ItsNeighborIndex.hpp +++ b/sandboxes/its_neighbor_index/ItsNeighborIndex.hpp @@ -2,6 +2,7 @@ #include "libslic3r/MeshSplitImpl.hpp" namespace Slic3r { +using FaceNeighborIndex = std::vector>; FaceNeighborIndex its_create_neighbors_index_1(const indexed_triangle_set &its); std::vector its_create_neighbors_index_2(const indexed_triangle_set &its); std::vector its_create_neighbors_index_3(const indexed_triangle_set &its); @@ -12,6 +13,7 @@ std::vector> its_create_neighbors_index_6(const indexed_tr std::vector> its_create_neighbors_index_7(const indexed_triangle_set &its); FaceNeighborIndex its_create_neighbors_index_8(const indexed_triangle_set &its); std::vector its_create_neighbors_index_9(const indexed_triangle_set &its); +std::vector its_create_neighbors_index_10(const indexed_triangle_set &its); std::vector> create_vertex_faces_index(const indexed_triangle_set &its); } diff --git a/sandboxes/its_neighbor_index/main.cpp b/sandboxes/its_neighbor_index/main.cpp index e53b51927a..2c89da3ac4 100644 --- a/sandboxes/its_neighbor_index/main.cpp +++ b/sandboxes/its_neighbor_index/main.cpp @@ -138,18 +138,18 @@ static const std::pair ToMeasure[] = { {"two_spheres_64x", two_spheres(8. * 60.)}, {"two_spheres_128x", two_spheres(sq2 * 8. * 60.)}, {"two_spheres_256x", two_spheres(16. * 60.)}, - {"two_spheres_512x", two_spheres(sq2 * 16. * 60.)} + {"two_spheres_512x", two_spheres(sq2 * 16. * 60.)}, -// {"2_spheres", make_spheres(2, 60.)}, -// {"4_spheres", make_spheres(4, 60.)}, -// {"8_spheres", make_spheres(8, 60.)}, -// {"16_spheres", make_spheres(16, 60.)}, -// {"32_spheres", make_spheres(32, 60.)}, -// {"64_spheres", make_spheres(64, 60.)}, -// {"128_spheres", make_spheres(128, 60.)}, -// {"256_spheres", make_spheres(256, 60.)}, -// {"512_spheres", make_spheres(512, 60.)}, -// {"1024_spheres", make_spheres(1024, 60.)} + {"2_spheres", make_spheres(2, 60.)}, + {"4_spheres", make_spheres(4, 60.)}, + {"8_spheres", make_spheres(8, 60.)}, + {"16_spheres", make_spheres(16, 60.)}, + {"32_spheres", make_spheres(32, 60.)}, + {"64_spheres", make_spheres(64, 60.)}, + {"128_spheres", make_spheres(128, 60.)}, + {"256_spheres", make_spheres(256, 60.)}, + {"512_spheres", make_spheres(512, 60.)}, + {"1024_spheres", make_spheres(1024, 60.)} }; static const auto IndexFunctions = std::make_tuple( @@ -158,6 +158,7 @@ static const auto IndexFunctions = std::make_tuple( std::make_pair("vojta tbb::parallel_sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_3); }), std::make_pair("filip's vertex->face based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_5); }), std::make_pair("vojta's vertex->face", [](const auto &its) { return measure_index(its, its_create_neighbors_index_9); }), + std::make_pair("vojta's vertex->face parallel", [](const auto &its) { return measure_index(its, its_create_neighbors_index_10); }), std::make_pair("tamas's std::sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_6); }), std::make_pair("tamas's tbb::parallel_sort based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_7); }), std::make_pair("tamas's map based", [](const auto &its) { return measure_index(its, its_create_neighbors_index_8); }), diff --git a/src/libslic3r/MeshSplitImpl.hpp b/src/libslic3r/MeshSplitImpl.hpp index 895fb83c65..feaa159b87 100644 --- a/src/libslic3r/MeshSplitImpl.hpp +++ b/src/libslic3r/MeshSplitImpl.hpp @@ -3,8 +3,13 @@ #include "TriangleMesh.hpp" #include "libnest2d/tools/benchmark.h" +#include "Execution/ExecutionTBB.hpp" namespace Slic3r { + +template +std::vector create_neighbors_index(ExPolicy &&ex, const indexed_triangle_set &its); + namespace meshsplit_detail { template struct ItsWithNeighborsIndex_ { @@ -19,7 +24,7 @@ template<> struct ItsWithNeighborsIndex_ { static const indexed_triangle_set &get_its(const indexed_triangle_set &its) noexcept { return its; } static Index get_index(const indexed_triangle_set &its) noexcept { - return its_create_neighbors_index(its); + return create_neighbors_index(ex_tbb, its); } }; @@ -152,12 +157,68 @@ template bool its_is_splittable(const Its &m) const auto& neighbor_index = ItsWithNeighborsIndex_::get_index(m); std::vector visited(its.indices.size(), false); - its_find_unvisited_neighbors(its, neighbor_index, visited); + auto faces = its_find_unvisited_neighbors(its, neighbor_index, visited); - // Try finding an unvisited facet. If there are none, the mesh is not splittable. - auto it = std::find(visited.begin(), visited.end(), false); + return !faces.empty(); +} - return it != visited.end(); +inline int get_vertex_index(size_t vertex_index, const stl_triangle_vertex_indices &triangle_indices) { + if (int(vertex_index) == triangle_indices[0]) return 0; + if (int(vertex_index) == triangle_indices[1]) return 1; + if (int(vertex_index) == triangle_indices[2]) return 2; + return -1; +} + +inline Vec2crd get_edge_indices(int edge_index, const stl_triangle_vertex_indices &triangle_indices) +{ + int next_edge_index = (edge_index == 2) ? 0 : edge_index + 1; + int vi0 = triangle_indices[edge_index]; + int vi1 = triangle_indices[next_edge_index]; + return Vec2crd(vi0, vi1); +} + +template +std::vector create_neighbors_index(ExPolicy &&ex, const indexed_triangle_set &its) +{ + const std::vector &indices = its.indices; + size_t vertices_size = its.vertices.size(); + + if (indices.empty() || vertices_size == 0) return {}; + + auto vertex_triangles = VertexFaceIndex{its}; + constexpr int no_value = -1; + std::vector neighbors(indices.size(), + Vec3i(no_value, no_value, no_value)); + + //for (const stl_triangle_vertex_indices& triangle_indices : indices) { + execution::for_each(ex, size_t(0), indices.size(), + [&neighbors, &indices, &vertex_triangles] (size_t index) + { + Vec3i& neighbor = neighbors[index]; + const stl_triangle_vertex_indices & triangle_indices = indices[index]; + for (int edge_index = 0; edge_index < 3; ++edge_index) { + // check if done + int& neighbor_edge = neighbor[edge_index]; + if (neighbor_edge != no_value) continue; + Vec2crd edge_indices = get_edge_indices(edge_index, triangle_indices); + // IMPROVE: use same vector for 2 sides of triangle + const auto &faces_range = vertex_triangles[edge_indices[0]]; + for (const size_t &face : faces_range) { + if (face <= index) continue; + const stl_triangle_vertex_indices &face_indices = indices[face]; + int vertex_index = get_vertex_index(edge_indices[1], face_indices); + // NOT Contain second vertex? + if (vertex_index < 0) continue; + // Has NOT oposit direction? + if (edge_indices[0] != face_indices[(vertex_index + 1) % 3]) continue; + neighbor_edge = face; + neighbors[face][vertex_index] = index; + break; + } + } + }, execution::max_concurrency(ex)); + + return neighbors; } } // namespace Slic3r diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index b81ab03736..00d77e8458 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -5,6 +5,8 @@ #include "ClipperUtils.hpp" #include "Geometry.hpp" #include "Point.hpp" +#include "Execution/ExecutionTBB.hpp" +#include "Execution/ExecutionSeq.hpp" #include #include @@ -1204,56 +1206,14 @@ void VertexFaceIndex::create(const indexed_triangle_set &its) m_vertex_to_face_start.front() = 0; } -static int get_vertex_index(size_t vertex_index, const stl_triangle_vertex_indices &triangle_indices) { - if (int(vertex_index) == triangle_indices[0]) return 0; - if (int(vertex_index) == triangle_indices[1]) return 1; - if (int(vertex_index) == triangle_indices[2]) return 2; - return -1; -} - -static Vec2crd get_edge_indices(int edge_index, const stl_triangle_vertex_indices &triangle_indices) -{ - int next_edge_index = (edge_index == 2) ? 0 : edge_index + 1; - coord_t vi0 = triangle_indices[edge_index]; - coord_t vi1 = triangle_indices[next_edge_index]; - return Vec2crd(vi0, vi1); -} - std::vector its_create_neighbors_index(const indexed_triangle_set &its) { - const std::vector &indices = its.indices; - size_t vertices_size = its.vertices.size(); + return create_neighbors_index(ex_seq, its); +} - if (indices.empty() || vertices_size == 0) return {}; - auto vertex_triangles = VertexFaceIndex{its}; - coord_t no_value = -1; - std::vector neighbors(indices.size(), Vec3i(no_value, no_value, no_value)); - for (const stl_triangle_vertex_indices& triangle_indices : indices) { - coord_t index = &triangle_indices - &indices.front(); - Vec3i& neighbor = neighbors[index]; - for (int edge_index = 0; edge_index < 3; ++edge_index) { - // check if done - coord_t& neighbor_edge = neighbor[edge_index]; - if (neighbor_edge != no_value) continue; - Vec2crd edge_indices = get_edge_indices(edge_index, triangle_indices); - // IMPROVE: use same vector for 2 sides of triangle - const auto &faces_range = vertex_triangles[edge_indices[0]]; - for (const size_t &face : faces_range) { - if (int(face) <= index) continue; - const stl_triangle_vertex_indices &face_indices = indices[face]; - int vertex_index = get_vertex_index(edge_indices[1], face_indices); - // NOT Contain second vertex? - if (vertex_index < 0) continue; - // Has NOT oposit direction? - if (edge_indices[0] != face_indices[(vertex_index + 1) % 3]) continue; - neighbor_edge = face; - neighbors[face][vertex_index] = index; - break; - } - } - } - - return neighbors; +std::vector its_create_neighbors_index_par(const indexed_triangle_set &its) +{ + return create_neighbors_index(ex_tbb, its); } } // namespace Slic3r diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index feacff2c2a..3d2364d36d 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -142,6 +142,11 @@ private: std::vector create_face_neighbors_index(const indexed_triangle_set &its); std::vector create_face_neighbors_index(const indexed_triangle_set &its, std::function throw_on_cancel_callback); +// Create index that gives neighbor faces for each face. Ignores face orientations. +// TODO: naming... +std::vector its_create_neighbors_index(const indexed_triangle_set &its); +std::vector its_create_neighbors_index_par(const indexed_triangle_set &its); + // After applying a transformation with negative determinant, flip the faces to keep the transformed mesh volume positive. void its_flip_triangles(indexed_triangle_set &its); @@ -156,11 +161,6 @@ int its_remove_degenerate_faces(indexed_triangle_set &its, bool shrink_to_fit = // Remove vertices, which none of the faces references. Return number of freed vertices. int its_compactify_vertices(indexed_triangle_set &its, bool shrink_to_fit = true); -using FaceNeighborIndex = std::vector< std::array >; - -// Create index that gives neighbor faces for each face. Ignores face orientations. -std::vector its_create_neighbors_index(const indexed_triangle_set &its); - std::vector its_split(const indexed_triangle_set &its); bool its_is_splittable(const indexed_triangle_set &its);