Browse Source

Refactored hollowing backend to use indexed_triangle_mesh

tamasmeszaros 3 years ago
parent
commit
e6f97358bc

+ 22 - 37
src/libslic3r/OpenVDBUtils.cpp

@@ -54,14 +54,16 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set &    mesh,
 {
     openvdb::initialize();
 
-    TriangleMeshPtrs meshparts_raw = mesh.split();
-    auto meshparts = reserve_vector<std::unique_ptr<TriangleMesh>>(meshparts_raw.size());
-    for (auto *p : meshparts_raw)
-        meshparts.emplace_back(p);
+    std::vector<indexed_triangle_set> meshparts;
+    its_split(mesh, std::back_inserter(meshparts));
+
+//    TriangleMeshPtrs meshparts_raw = mesh.split();
+//    auto meshparts = reserve_vector<std::unique_ptr<TriangleMesh>>(meshparts_raw.size());
+//    for (auto *p : meshparts_raw)
+//        meshparts.emplace_back(p);
 
     auto it = std::remove_if(meshparts.begin(), meshparts.end(), [](auto &m) {
-         m->require_shared_vertices();
-         return m->volume() < EPSILON;
+        return its_volume(m) < EPSILON;
      });
 
     meshparts.erase(it, meshparts.end());
@@ -69,7 +71,7 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set &    mesh,
     openvdb::FloatGrid::Ptr grid;
     for (auto &m : meshparts) {
         auto subgrid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
-            TriangleMeshDataAdapter{*m, voxel_scale}, tr, exteriorBandWidth,
+            TriangleMeshDataAdapter{m, voxel_scale}, tr, exteriorBandWidth,
             interiorBandWidth, flags);
 
         if (grid && subgrid) openvdb::tools::csgUnion(*grid, *subgrid);
@@ -91,11 +93,10 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set &    mesh,
     return grid;
 }
 
-template<class Grid>
-sla::Contour3D _volumeToMesh(const Grid &grid,
-                             double      isovalue,
-                             double      adaptivity,
-                             bool        relaxDisorientedTriangles)
+indexed_triangle_set grid_to_mesh(const openvdb::FloatGrid &grid,
+                          double                    isovalue,
+                          double                    adaptivity,
+                          bool                      relaxDisorientedTriangles)
 {
     openvdb::initialize();
 
@@ -111,36 +112,20 @@ sla::Contour3D _volumeToMesh(const Grid &grid,
         scale = grid.template metaValue<float>("voxel_scale");
     }  catch (...) { }
 
-    sla::Contour3D ret;
-    ret.points.reserve(points.size());
-    ret.faces3.reserve(triangles.size());
-    ret.faces4.reserve(quads.size());
+    indexed_triangle_set ret;
+    ret.vertices.reserve(points.size());
+    ret.indices.reserve(triangles.size() + quads.size() * 2);
 
-    for (auto &v : points) ret.points.emplace_back(to_vec3d(v) / scale);
-    for (auto &v : triangles) ret.faces3.emplace_back(to_vec3i(v));
-    for (auto &v : quads) ret.faces4.emplace_back(to_vec4i(v));
+    for (auto &v : points) ret.vertices.emplace_back(to_vec3f(v) / scale);
+    for (auto &v : triangles) ret.indices.emplace_back(to_vec3i(v));
+    for (auto &quad : quads) {
+        ret.indices.emplace_back(quad(0), quad(1), quad(2));
+        ret.indices.emplace_back(quad(2), quad(3), quad(0));
+    }
 
     return ret;
 }
 
-TriangleMesh grid_to_mesh(const openvdb::FloatGrid &grid,
-                          double                    isovalue,
-                          double                    adaptivity,
-                          bool                      relaxDisorientedTriangles)
-{
-    return to_triangle_mesh(
-        _volumeToMesh(grid, isovalue, adaptivity, relaxDisorientedTriangles));
-}
-
-sla::Contour3D grid_to_contour3d(const openvdb::FloatGrid &grid,
-                                 double                    isovalue,
-                                 double                    adaptivity,
-                                 bool relaxDisorientedTriangles)
-{
-    return _volumeToMesh(grid, isovalue, adaptivity,
-                         relaxDisorientedTriangles);
-}
-
 openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid,
                                         double                    iso,
                                         double                    er,

+ 0 - 5
src/libslic3r/OpenVDBUtils.hpp

@@ -35,11 +35,6 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set &    mesh,
                                      float interiorBandWidth = 3.0f,
                                      int   flags             = 0);
 
-sla::Contour3D grid_to_contour3d(const openvdb::FloatGrid &grid,
-                                 double                    isovalue,
-                                 double                    adaptivity,
-                                 bool relaxDisorientedTriangles = true);
-
 indexed_triangle_set grid_to_mesh(const openvdb::FloatGrid &grid,
                                   double                    isovalue   = 0.0,
                                   double                    adaptivity = 0.0,

+ 8 - 12
src/libslic3r/SLA/Hollowing.cpp

@@ -77,7 +77,7 @@ static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh,
     if (ctl.stopcondition()) return {};
     else ctl.statuscb(0, L("Hollowing"));
 
-    auto gridptr = mesh_to_grid(mesh, {}, voxel_scale, out_range, in_range);
+    auto gridptr = mesh_to_grid(mesh.its, {}, voxel_scale, out_range, in_range);
 
     assert(gridptr);
 
@@ -136,19 +136,15 @@ InteriorPtr generate_interior(const TriangleMesh &   mesh,
 
     if (interior && !interior->mesh.empty()) {
 
-        // This flips the normals to be outward facing...
-        interior->mesh.require_shared_vertices();
-        indexed_triangle_set its = std::move(interior->mesh.its);
+        // flip normals back...
+        swap_normals(interior->mesh);
+        Slic3r::simplify_mesh(interior->mesh);
 
-        Slic3r::simplify_mesh(its);
+        its_compactify_vertices(interior->mesh);
+        its_merge_vertices(interior->mesh);
 
         // flip normals back...
-        for (stl_triangle_vertex_indices &ind : its.indices)
-            std::swap(ind(0), ind(2));
-
-        interior->mesh = Slic3r::TriangleMesh{its};
-        interior->mesh.repaired = true;
-        interior->mesh.require_shared_vertices();
+        swap_normals(interior->mesh);
     }
 
     return interior;
@@ -325,7 +321,7 @@ void hollow_mesh(TriangleMesh &mesh, const Interior &interior, int flags)
     if (flags & hfRemoveInsideTriangles && interior.gridptr)
         remove_inside_triangles(mesh, interior);
 
-    mesh.merge(interior.mesh);
+    mesh.merge(TriangleMesh{interior.mesh});
     mesh.require_shared_vertices();
 }
 

+ 6 - 0
src/libslic3r/SLA/Hollowing.hpp

@@ -99,6 +99,12 @@ void cut_drainholes(std::vector<ExPolygons> & obj_slices,
                     const sla::DrainHoles &   holes,
                     std::function<void(void)> thr);
 
+inline void swap_normals(indexed_triangle_set &its)
+{
+    for (auto &face : its.indices)
+        std::swap(face(0), face(2));
+}
+
 } // namespace sla
 } // namespace Slic3r
 

+ 0 - 1
src/libslic3r/SLA/Pad.cpp

@@ -480,7 +480,6 @@ void pad_blueprint(const indexed_triangle_set &mesh,
 {
     if (mesh.empty()) return;
 
-    assert(mesh.has_shared_vertices());
     std::vector<ExPolygons> out = slice_mesh_ex(mesh, heights, thrfn);
 
     size_t count = 0;

+ 0 - 2
src/libslic3r/SLA/SupportTree.cpp

@@ -45,7 +45,6 @@ std::vector<ExPolygons> SupportTree::slice(const std::vector<float> &grid,
 
     if (!sup_mesh.empty()) {
         slices.emplace_back();
-        assert(sup_mesh.has_shared_vertices());
         slices.back() = slice_mesh_ex(sup_mesh, grid, cr, ctl().cancelfn);
     }
 
@@ -59,7 +58,6 @@ std::vector<ExPolygons> SupportTree::slice(const std::vector<float> &grid,
         auto padgrid = reserve_vector<float>(size_t(cap > 0 ? cap : 0));
         std::copy(grid.begin(), maxzit, std::back_inserter(padgrid));
 
-        assert(pad_mesh.has_shared_vertices());
         slices.back() = slice_mesh_ex(pad_mesh, padgrid, cr, ctl().cancelfn);
     }
 

+ 3 - 2
src/libslic3r/SLAPrint.cpp

@@ -1067,6 +1067,7 @@ Vec3d SLAPrint::relative_correction() const
 namespace { // dummy empty static containers for return values in some methods
 const std::vector<ExPolygons> EMPTY_SLICES;
 const TriangleMesh EMPTY_MESH;
+const indexed_triangle_set EMPTY_TRIANGLE_SET;
 const ExPolygons EMPTY_SLICE;
 const std::vector<sla::SupportPoint> EMPTY_SUPPORT_POINTS;
 }
@@ -1143,13 +1144,13 @@ const TriangleMesh& SLAPrintObject::pad_mesh() const
     return EMPTY_MESH;
 }
 
-const TriangleMesh &SLAPrintObject::hollowed_interior_mesh() const
+const indexed_triangle_set &SLAPrintObject::hollowed_interior_mesh() const
 {
     if (m_hollowing_data && m_hollowing_data->interior &&
         m_config.hollowing_enable.getBool())
         return sla::get_mesh(*m_hollowing_data->interior);
     
-    return EMPTY_MESH;
+    return EMPTY_TRIANGLE_SET;
 }
 
 const TriangleMesh &SLAPrintObject::transformed_mesh() const {

+ 2 - 2
src/libslic3r/SLAPrint.hpp

@@ -79,8 +79,8 @@ public:
     const TriangleMesh&     pad_mesh() const;
     
     // Ready after this->is_step_done(slaposDrillHoles) is true
-    const TriangleMesh&     hollowed_interior_mesh() const;
-    
+    const indexed_triangle_set &hollowed_interior_mesh() const;
+
     // Get the mesh that is going to be printed with all the modifications
     // like hollowing and drilled holes.
     const TriangleMesh & get_mesh_to_print() const {

+ 5 - 5
src/libslic3r/SLAPrintSteps.cpp

@@ -194,7 +194,7 @@ static std::vector<bool> create_exclude_mask(
         const sla::Interior &interior,
         const std::vector<sla::DrainHole> &holes)
 {
-    FaceHash interior_hash{sla::get_mesh(interior).its};
+    FaceHash interior_hash{sla::get_mesh(interior)};
 
     std::vector<bool> exclude_mask(its.indices.size(), false);
 
@@ -489,11 +489,11 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
                                   nullptr;
 
     if (interior && ! sla::get_mesh(*interior).empty()) {
-        TriangleMesh interiormesh = sla::get_mesh(*interior);
-        interiormesh.repaired = false;
-        interiormesh.repair(true);
+        indexed_triangle_set interiormesh = sla::get_mesh(*interior);
+        sla::swap_normals(interiormesh);
         params.mode = MeshSlicingParams::SlicingMode::Regular;
-        std::vector<ExPolygons> interior_slices = slice_mesh_ex(interiormesh.its, slice_grid, params, thr);
+
+        std::vector<ExPolygons> interior_slices = slice_mesh_ex(interiormesh, slice_grid, closing_r, thr);
 
         sla::ccr::for_each(size_t(0), interior_slices.size(),
                            [&po, &interior_slices] (size_t i) {

+ 63 - 0
src/libslic3r/TriangleMesh.cpp

@@ -1161,4 +1161,67 @@ void its_merge(indexed_triangle_set &A, const Pointf3s &triangles)
     its_merge(A, trianglesf);
 }
 
+float its_volume(const indexed_triangle_set &its)
+{
+    if (its.empty()) return 0.;
+
+    // Choose a point, any point as the reference.
+    auto p0 = its.vertices.front();
+    float volume = 0.f;
+    for (size_t i = 0; i < its.indices.size(); ++ i) {
+        // Do dot product to get distance from point to plane.
+        its_triangle triangle = its_triangle_vertices(its, i);
+        Vec3f U = triangle[1] - triangle[0];
+        Vec3f V = triangle[2] - triangle[0];
+        Vec3f C = U.cross(V);
+        Vec3f normal = C.normalized();
+        float area = 0.5 * C.norm();
+        float height = normal.dot(triangle[0] - p0);
+        volume += (area * height) / 3.0f;
+    }
+
+    return volume;
+}
+
+PartMap::PartMap(const indexed_triangle_set &            its,
+                 const std::vector<std::vector<size_t>> &vfidx)
+    : count(0), face_part_indices(its.indices.size(), UNVISITED)
+{
+    auto next_face_idx = [this](size_t start) {
+        size_t i = start;
+        while (face_part_indices[i++] >= 0);
+        return i;
+    };
+
+    size_t face_idx = 0;
+    size_t part_idx = 0;
+
+    do {
+        face_idx = next_face_idx(face_idx);
+    } while(split_recurse(its, vfidx, face_idx, part_idx++));
+
+    count = size_t(part_idx - 1);
 }
+
+bool PartMap::split_recurse(const indexed_triangle_set &            its,
+                            const std::vector<std::vector<size_t>> &vfidx,
+                            size_t                                  fi,
+                            size_t                                  part_idx)
+{
+    if (face_part_indices[fi] >= 0)
+        return false;
+
+    face_part_indices[fi] = part_idx;
+    const auto &face = its.indices[fi];
+
+    for (size_t v = 0; v < 3; ++v) {
+        auto vi = face(v);
+        const std::vector<size_t> neigh_faces = vfidx[vi];
+        for (size_t neigh_face : neigh_faces)
+            split_recurse(its, vfidx, neigh_face, part_idx);
+    }
+
+    return true;
+}
+
+} // namespace Slic3r

Some files were not shown because too many files changed in this diff