From c4c8b7608e795323e39e949ab08fa85e9416af6c Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 5 Nov 2021 15:32:14 +0100 Subject: [PATCH] Fix some mesh errors in sl1 archive reconstruction --- src/libslic3r/SlicesToTriangleMesh.cpp | 59 +++++++++++++------------- src/libslic3r/SlicesToTriangleMesh.hpp | 8 ++-- src/libslic3r/TriangleMesh.cpp | 26 +++++------- src/slic3r/GUI/Jobs/SLAImportJob.cpp | 2 +- 4 files changed, 45 insertions(+), 50 deletions(-) diff --git a/src/libslic3r/SlicesToTriangleMesh.cpp b/src/libslic3r/SlicesToTriangleMesh.cpp index 7a2975d12d..3b55cf066b 100644 --- a/src/libslic3r/SlicesToTriangleMesh.cpp +++ b/src/libslic3r/SlicesToTriangleMesh.cpp @@ -1,3 +1,4 @@ +#include #include "SlicesToTriangleMesh.hpp" @@ -22,11 +23,16 @@ inline indexed_triangle_set wall_strip(const Polygon &poly, ret.vertices.reserve(ret.vertices.size() + 2 *offs); + // The expression unscaled(p).cast().eval() is important here + // as it ensures identical conversion of 2D scaled coordinates to float 3D + // to that used by the tesselation. This way, the duplicated vertices in the + // output mesh can be found with the == operator of the points. + // its_merge_vertices will then reliably remove the duplicates. for (const Point &p : poly.points) - ret.vertices.emplace_back(to_3d(unscaled(p), float(lower_z_mm))); + ret.vertices.emplace_back(to_3d(unscaled(p).cast().eval(), float(lower_z_mm))); for (const Point &p : poly.points) - ret.vertices.emplace_back(to_3d(unscaled(p), float(upper_z_mm))); + ret.vertices.emplace_back(to_3d(unscaled(p).cast().eval(), float(upper_z_mm))); for (size_t i = startidx + 1; i < startidx + offs; ++i) { ret.indices.emplace_back(i - 1, i, i + offs - 1); @@ -84,12 +90,14 @@ indexed_triangle_set slices_to_mesh( const ExPolygons &upper = slices[i + 1]; const ExPolygons &lower = slices[i]; - ExPolygons dff1 = diff_ex(lower, upper); - ExPolygons dff2 = diff_ex(upper, lower); - its_merge(layers[i], triangulate_expolygons_3d(dff1, grid[i], NORMALS_UP)); - its_merge(layers[i], triangulate_expolygons_3d(dff2, grid[i], NORMALS_DOWN)); + // Small 0 area artefacts can be created by diff_ex, and the + // tesselation also can create 0 area triangles. These will be removed + // by its_remove_degenerate_faces. + ExPolygons free_top = diff_ex(lower, upper); + ExPolygons overhang = diff_ex(upper, lower); + its_merge(layers[i], triangulate_expolygons_3d(free_top, grid[i], NORMALS_UP)); + its_merge(layers[i], triangulate_expolygons_3d(overhang, grid[i], NORMALS_DOWN)); its_merge(layers[i], straight_walls(upper, grid[i], grid[i + 1])); - }); auto merge_fn = []( const indexed_triangle_set &a, const indexed_triangle_set &b ) { @@ -99,37 +107,30 @@ indexed_triangle_set slices_to_mesh( auto ret = execution::reduce(ex_tbb, layers.begin(), layers.end(), indexed_triangle_set{}, merge_fn); - // sla::Contour3D ret = tbb::parallel_reduce( - // tbb::blocked_range(layers.begin(), layers.end()), - // sla::Contour3D{}, - // [](const tbb::blocked_range& r, sla::Contour3D - // init) { - // for(auto it = r.begin(); it != r.end(); ++it ) - // init.merge(*it); return init; - // }, - // []( const sla::Contour3D &a, const sla::Contour3D &b ) { - // sla::Contour3D res{a}; res.merge(b); return res; - // }); - its_merge(ret, triangulate_expolygons_3d(slices.front(), zmin, NORMALS_DOWN)); its_merge(ret, straight_walls(slices.front(), zmin, grid.front())); its_merge(ret, triangulate_expolygons_3d(slices.back(), grid.back(), NORMALS_UP)); - + + // FIXME: these repairs do not fix the mesh entirely. There will be cracks + // in the output. It is very hard to do the meshing in a way that does not + // leave errors. + its_merge_vertices(ret); + its_remove_degenerate_faces(ret); + its_compactify_vertices(ret); + return ret; } void slices_to_mesh(indexed_triangle_set & mesh, - const std::vector &slices, - double zmin, - double lh, - double ilh) + const std::vector &slices, + double zmin, + double lh, + double ilh) { - std::vector wall_meshes(slices.size()); std::vector grid(slices.size(), zmin + ilh); - - for (size_t i = 1; i < grid.size(); ++i) - grid[i] = grid[i - 1] + lh; - + + for (size_t i = 1; i < grid.size(); ++i) grid[i] = grid[i - 1] + lh; + indexed_triangle_set cntr = slices_to_mesh(slices, zmin, grid); its_merge(mesh, cntr); } diff --git a/src/libslic3r/SlicesToTriangleMesh.hpp b/src/libslic3r/SlicesToTriangleMesh.hpp index 2fd1778851..57b540d9fb 100644 --- a/src/libslic3r/SlicesToTriangleMesh.hpp +++ b/src/libslic3r/SlicesToTriangleMesh.hpp @@ -7,10 +7,10 @@ namespace Slic3r { void slices_to_mesh(indexed_triangle_set & mesh, - const std::vector &slices, - double zmin, - double lh, - double ilh); + const std::vector &slices, + double zmin, + double lh, + double ilh); inline indexed_triangle_set slices_to_mesh( const std::vector &slices, double zmin, double lh, double ilh) diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index fb2621225a..efd8e97f71 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -705,22 +705,16 @@ void its_flip_triangles(indexed_triangle_set &its) int its_remove_degenerate_faces(indexed_triangle_set &its, bool shrink_to_fit) { - int last = 0; - for (int i = 0; i < int(its.indices.size()); ++ i) { - const stl_triangle_vertex_indices &face = its.indices[i]; - if (face(0) != face(1) && face(0) != face(2) && face(1) != face(2)) { - if (last < i) - its.indices[last] = its.indices[i]; - ++ last; - } - } - int removed = int(its.indices.size()) - last; - if (removed) { - its.indices.erase(its.indices.begin() + last, its.indices.end()); - // Optionally shrink the vertices. - if (shrink_to_fit) - its.indices.shrink_to_fit(); - } + auto it = std::remove_if(its.indices.begin(), its.indices.end(), [](auto &face) { + return face(0) == face(1) || face(0) == face(2) || face(1) == face(2); + }); + + int removed = std::distance(it, its.indices.end()); + its.indices.erase(it, its.indices.end()); + + if (removed && shrink_to_fit) + its.indices.shrink_to_fit(); + return removed; } diff --git a/src/slic3r/GUI/Jobs/SLAImportJob.cpp b/src/slic3r/GUI/Jobs/SLAImportJob.cpp index 287b2e88be..0d42cec2d3 100644 --- a/src/slic3r/GUI/Jobs/SLAImportJob.cpp +++ b/src/slic3r/GUI/Jobs/SLAImportJob.cpp @@ -236,7 +236,7 @@ void SLAImportJob::finalize() if (!p->mesh.empty()) { bool is_centered = false; - p->plater->sidebar().obj_list()->load_mesh_object(TriangleMesh{p->mesh}, + p->plater->sidebar().obj_list()->load_mesh_object(TriangleMesh{std::move(p->mesh)}, name, is_centered); }