From 9e5ba20f8f3aefb93037de4968799afa685c90ec Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Mon, 4 Apr 2022 16:37:58 +0200 Subject: [PATCH 1/8] Use default bandwidth before csgUnion when hollowing Add cca 6.5% speedup (on 12 core amd) --- src/libslic3r/OpenVDBUtils.cpp | 8 +++----- src/libslic3r/OpenVDBUtils.hpp | 3 +-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/OpenVDBUtils.cpp b/src/libslic3r/OpenVDBUtils.cpp index 72c7668a4..188ff8fb9 100644 --- a/src/libslic3r/OpenVDBUtils.cpp +++ b/src/libslic3r/OpenVDBUtils.cpp @@ -49,8 +49,7 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set & mesh, const openvdb::math::Transform &tr, float voxel_scale, float exteriorBandWidth, - float interiorBandWidth, - int flags) + float interiorBandWidth) { openvdb::initialize(); @@ -64,8 +63,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( - TriangleMeshDataAdapter{m, voxel_scale}, tr, exteriorBandWidth, - interiorBandWidth, flags); + TriangleMeshDataAdapter{m, voxel_scale}, tr); if (grid && subgrid) openvdb::tools::csgUnion(*grid, *subgrid); else if (subgrid) grid = std::move(subgrid); @@ -78,7 +76,7 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set & mesh, // Splitting failed, fall back to hollow the original mesh grid = openvdb::tools::meshToVolume( TriangleMeshDataAdapter{mesh}, tr, exteriorBandWidth, - interiorBandWidth, flags); + interiorBandWidth); } grid->insertMeta("voxel_scale", openvdb::FloatMetadata(voxel_scale)); diff --git a/src/libslic3r/OpenVDBUtils.hpp b/src/libslic3r/OpenVDBUtils.hpp index 490b3e222..1387af670 100644 --- a/src/libslic3r/OpenVDBUtils.hpp +++ b/src/libslic3r/OpenVDBUtils.hpp @@ -30,8 +30,7 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set & mesh, const openvdb::math::Transform &tr = {}, float voxel_scale = 1.f, float exteriorBandWidth = 3.0f, - float interiorBandWidth = 3.0f, - int flags = 0); + float interiorBandWidth = 3.0f); indexed_triangle_set grid_to_mesh(const openvdb::FloatGrid &grid, double isovalue = 0.0, From 1a6a2a0b9a53da907355a577f18ce07323bbdca5 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Wed, 6 Apr 2022 15:58:59 +0200 Subject: [PATCH 2/8] 2.5x speedup of hollowing. Triangle removal is slightly broken --- src/libslic3r/OpenVDBUtils.cpp | 32 +++++++++++++++++++++++++++----- src/libslic3r/OpenVDBUtils.hpp | 7 +++++-- src/libslic3r/SLA/Hollowing.cpp | 18 +++++++++++++----- src/libslic3r/SLAPrintSteps.cpp | 11 ++++++++++- 4 files changed, 55 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/OpenVDBUtils.cpp b/src/libslic3r/OpenVDBUtils.cpp index 188ff8fb9..603362b69 100644 --- a/src/libslic3r/OpenVDBUtils.cpp +++ b/src/libslic3r/OpenVDBUtils.cpp @@ -14,6 +14,7 @@ #include #include #include +#include //#include "MTUtils.hpp" @@ -69,16 +70,26 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set & mesh, else if (subgrid) grid = std::move(subgrid); } - if (grid) { - grid = openvdb::tools::levelSetRebuild(*grid, 0., exteriorBandWidth, - interiorBandWidth); + if (grid && meshparts.size() >= 1) { +// grid = openvdb::tools::levelSetRebuild(*grid, 0.); } else if(meshparts.empty()) { // Splitting failed, fall back to hollow the original mesh grid = openvdb::tools::meshToVolume( - TriangleMeshDataAdapter{mesh}, tr, exteriorBandWidth, - interiorBandWidth); + TriangleMeshDataAdapter{mesh}, tr); } + constexpr int DilateIterations = 1; + + grid = openvdb::tools::dilateSdf( + *grid, interiorBandWidth, openvdb::tools::NN_FACE_EDGE, + DilateIterations, + openvdb::tools::FastSweepingDomain::SWEEP_LESS_THAN_ISOVALUE); + + grid = openvdb::tools::dilateSdf( + *grid, exteriorBandWidth, openvdb::tools::NN_FACE_EDGE, + DilateIterations, + openvdb::tools::FastSweepingDomain::SWEEP_GREATER_THAN_ISOVALUE); + grid->insertMeta("voxel_scale", openvdb::FloatMetadata(voxel_scale)); return grid; @@ -131,4 +142,15 @@ openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid, return new_grid; } +openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid, + double iso) +{ + auto new_grid = openvdb::tools::levelSetRebuild(grid, float(iso)); + + // Copies voxel_scale metadata, if it exists. + new_grid->insertMeta(*grid.deepCopyMeta()); + + return new_grid; +} + } // namespace Slic3r diff --git a/src/libslic3r/OpenVDBUtils.hpp b/src/libslic3r/OpenVDBUtils.hpp index 1387af670..254ae3583 100644 --- a/src/libslic3r/OpenVDBUtils.hpp +++ b/src/libslic3r/OpenVDBUtils.hpp @@ -37,10 +37,13 @@ indexed_triangle_set grid_to_mesh(const openvdb::FloatGrid &grid, double adaptivity = 0.0, bool relaxDisorientedTriangles = true); +openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid, + double iso); + openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid, double iso, - double ext_range = 3., - double int_range = 3.); + double ext_range, + double int_range); } // namespace Slic3r diff --git a/src/libslic3r/SLA/Hollowing.cpp b/src/libslic3r/SLA/Hollowing.cpp index b0d33a0ca..81a38f3a9 100644 --- a/src/libslic3r/SLA/Hollowing.cpp +++ b/src/libslic3r/SLA/Hollowing.cpp @@ -12,6 +12,8 @@ #include +#include + #include #include @@ -65,13 +67,12 @@ static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh, { double offset = voxel_scale * min_thickness; double D = voxel_scale * closing_dist; - float out_range = 0.1f * float(offset); - float in_range = 1.1f * float(offset + D); + float in_range = /*1.1f * */float(offset + D); if (ctl.stopcondition()) return {}; else ctl.statuscb(0, L("Hollowing")); - auto gridptr = mesh_to_grid(mesh.its, {}, voxel_scale, out_range, in_range); + auto gridptr = mesh_to_grid(mesh.its, {}, voxel_scale, 3., in_range); assert(gridptr); @@ -84,9 +85,16 @@ static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh, else ctl.statuscb(30, L("Hollowing")); double iso_surface = D; - auto narrowb = double(in_range); + auto narrowb = 3.; //double(in_range); gridptr = redistance_grid(*gridptr, -(offset + D), narrowb, narrowb); + constexpr int DilateIterations = 1; + + gridptr = openvdb::tools::dilateSdf( + *gridptr, std::ceil(iso_surface), + openvdb::tools::NN_FACE_EDGE_VERTEX, DilateIterations, + openvdb::tools::FastSweepingDomain::SWEEP_GREATER_THAN_ISOVALUE); + if (ctl.stopcondition()) return {}; else ctl.statuscb(70, L("Hollowing")); @@ -103,7 +111,7 @@ static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh, interior->thickness = offset; interior->voxel_scale = voxel_scale; interior->nb_in = narrowb; - interior->nb_out = narrowb; + interior->nb_out = iso_surface; return interior; } diff --git a/src/libslic3r/SLAPrintSteps.cpp b/src/libslic3r/SLAPrintSteps.cpp index 435e8c8e3..02cdc4248 100644 --- a/src/libslic3r/SLAPrintSteps.cpp +++ b/src/libslic3r/SLAPrintSteps.cpp @@ -21,6 +21,8 @@ #include "I18N.hpp" +#include + //! macro used to mark string used at localization, //! return same string #define L(s) Slic3r::I18N::translate(s) @@ -1116,7 +1118,14 @@ double SLAPrint::Steps::progressrange(SLAPrintStep step) const void SLAPrint::Steps::execute(SLAPrintObjectStep step, SLAPrintObject &obj) { switch(step) { - case slaposHollowing: hollow_model(obj); break; + case slaposHollowing: { + Benchmark bench; + bench.start(); + hollow_model(obj); + bench.stop(); + std::cout << "Hollowing took " << bench.getElapsedSec() << " seconds" << std::endl; + break; + } case slaposDrillHoles: drill_holes(obj); break; case slaposObjectSlice: slice_model(obj); break; case slaposSupportPoints: support_points(obj); break; From b5bf529551bb7e271fb4449d567dc6a2e62127fe Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 7 Apr 2022 12:11:28 +0200 Subject: [PATCH 3/8] Solve missing faces of the interior in connection with the holes --- src/libslic3r/SLAPrintSteps.cpp | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/libslic3r/SLAPrintSteps.cpp b/src/libslic3r/SLAPrintSteps.cpp index 02cdc4248..b8aa62064 100644 --- a/src/libslic3r/SLAPrintSteps.cpp +++ b/src/libslic3r/SLAPrintSteps.cpp @@ -217,6 +217,22 @@ struct FaceHash { } }; +static void exclude_neighbors(const Vec3i &face, + std::vector &mask, + const indexed_triangle_set &its, + const VertexFaceIndex &index, + size_t recursions) +{ + for (int i = 0; i < 3; ++i) { + const auto &neighbors_range = index[face(i)]; + for (size_t fi_n : neighbors_range) { + mask[fi_n] = true; + if (recursions > 0) + exclude_neighbors(its.indices[fi_n], mask, its, index, recursions - 1); + } + } +} + // Create exclude mask for triangle removal inside hollowed interiors. // This is necessary when the interior is already part of the mesh which was // drilled using CGAL mesh boolean operation. Excluded will be the triangles @@ -233,15 +249,6 @@ static std::vector create_exclude_mask( VertexFaceIndex neighbor_index{its}; - auto exclude_neighbors = [&neighbor_index, &exclude_mask](const Vec3i &face) - { - for (int i = 0; i < 3; ++i) { - const auto &neighbors_range = neighbor_index[face(i)]; - for (size_t fi_n : neighbors_range) - exclude_mask[fi_n] = true; - } - }; - for (size_t fi = 0; fi < its.indices.size(); ++fi) { auto &face = its.indices[fi]; @@ -251,7 +258,7 @@ static std::vector create_exclude_mask( } if (exclude_mask[fi]) { - exclude_neighbors(face); + exclude_neighbors(face, exclude_mask, its, neighbor_index, 1); continue; } @@ -296,7 +303,7 @@ static std::vector create_exclude_mask( if (D_hole < D_tol && std::abs(dot) < normal_angle_tol) { exclude_mask[fi] = true; - exclude_neighbors(face); + exclude_neighbors(face, exclude_mask, its, neighbor_index, 1); } } } From e405b0ef4a6333ae6159f8652008c408ace47248 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 7 Apr 2022 12:11:37 +0200 Subject: [PATCH 4/8] Cleanup --- src/libslic3r/OpenVDBUtils.cpp | 8 ++------ src/libslic3r/SLA/Hollowing.cpp | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/OpenVDBUtils.cpp b/src/libslic3r/OpenVDBUtils.cpp index 603362b69..04bc92b4b 100644 --- a/src/libslic3r/OpenVDBUtils.cpp +++ b/src/libslic3r/OpenVDBUtils.cpp @@ -43,15 +43,13 @@ public: : its{m}, voxel_scale{voxel_sc} {}; }; -// TODO: Do I need to call initialize? Seems to work without it as well but the -// docs say it should be called ones. It does a mutex lock-unlock sequence all -// even if was called previously. openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set & mesh, const openvdb::math::Transform &tr, float voxel_scale, float exteriorBandWidth, float interiorBandWidth) { + // Might not be needed but this is now proven to be working openvdb::initialize(); std::vector meshparts = its_split(mesh); @@ -70,9 +68,7 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set & mesh, else if (subgrid) grid = std::move(subgrid); } - if (grid && meshparts.size() >= 1) { -// grid = openvdb::tools::levelSetRebuild(*grid, 0.); - } else if(meshparts.empty()) { + if(meshparts.empty()) { // Splitting failed, fall back to hollow the original mesh grid = openvdb::tools::meshToVolume( TriangleMeshDataAdapter{mesh}, tr); diff --git a/src/libslic3r/SLA/Hollowing.cpp b/src/libslic3r/SLA/Hollowing.cpp index 81a38f3a9..ab09372a7 100644 --- a/src/libslic3r/SLA/Hollowing.cpp +++ b/src/libslic3r/SLA/Hollowing.cpp @@ -502,7 +502,7 @@ void remove_inside_triangles(TriangleMesh &mesh, const Interior &interior, if (f.parent != NEW_FACE) // Top parent needs to be removed as well mesh_mods.to_remove[f.parent] = true; - // If the outside part is between the interior end the exterior + // If the outside part is between the interior and the exterior // (inside the wall being invisible), no further division is needed. if ((R + D) < interior.thickness) return false; From d1b161b281d23453e16e9ecaa1d5ad2840040438 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 8 Apr 2022 13:59:09 +0200 Subject: [PATCH 5/8] Hollowing voxel_scale now considers input model volume --- src/libslic3r/SLA/Hollowing.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/libslic3r/SLA/Hollowing.cpp b/src/libslic3r/SLA/Hollowing.cpp index ab09372a7..4a33dec7d 100644 --- a/src/libslic3r/SLA/Hollowing.cpp +++ b/src/libslic3r/SLA/Hollowing.cpp @@ -120,8 +120,9 @@ InteriorPtr generate_interior(const TriangleMesh & mesh, const HollowingConfig &hc, const JobController & ctl) { - static const double MIN_OVERSAMPL = 3.5; - static const double MAX_OVERSAMPL = 8.; + static constexpr double MIN_OVERSAMPL = 1.; + static constexpr double MAX_OVERSAMPL = 10.; + static constexpr double UNIT_VOLUME = 500000; // empiric // I can't figure out how to increase the grid resolution through openvdb // API so the model will be scaled up before conversion and the result @@ -129,8 +130,22 @@ InteriorPtr generate_interior(const TriangleMesh & mesh, // scales the whole geometry down, and doesn't increase the number of // voxels. // - // max 8x upscale, min is native voxel size - auto voxel_scale = MIN_OVERSAMPL + (MAX_OVERSAMPL - MIN_OVERSAMPL) * hc.quality; + // the voxel_scale will always reside between MIN_OVERSAMPL and + // a dynamically derived maximum (based on the model volume) + // which is always less than MAX_OVERSAMPL. The quality parameter will + // control the actual position of the scaling between this allowed range. + // + // For smaller models, the maximum can get up to MAX_OVERSAMPL + // for bigger models (reference unit volume is VOL_SCALING) the maximum + // is gradually decreased. + double mesh_vol = its_volume(mesh.its); + double sc_divider = std::max(1.0, (mesh_vol / UNIT_VOLUME)); + double max_oversampl_scaled = std::max(MIN_OVERSAMPL, + MAX_OVERSAMPL / sc_divider); + auto voxel_scale = MIN_OVERSAMPL + (max_oversampl_scaled - MIN_OVERSAMPL) * hc.quality; + BOOST_LOG_TRIVIAL(debug) << "Hollowing: max oversampl will be: " << max_oversampl_scaled; + BOOST_LOG_TRIVIAL(debug) << "Hollowing: voxel scale will be: " << voxel_scale; + BOOST_LOG_TRIVIAL(debug) << "Hollowing: mesh volume is: " << mesh_vol; InteriorPtr interior = generate_interior_verbose(mesh, ctl, hc.min_thickness, voxel_scale, From 23db6f3071b385afd111a0a2c97bff4b4dc25eb0 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 8 Apr 2022 13:59:40 +0200 Subject: [PATCH 6/8] Additional performance tuning by decreasing accuracy --- src/libslic3r/OpenVDBUtils.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libslic3r/OpenVDBUtils.cpp b/src/libslic3r/OpenVDBUtils.cpp index 04bc92b4b..c14dc7e63 100644 --- a/src/libslic3r/OpenVDBUtils.cpp +++ b/src/libslic3r/OpenVDBUtils.cpp @@ -62,7 +62,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( - TriangleMeshDataAdapter{m, voxel_scale}, tr); + TriangleMeshDataAdapter{m, voxel_scale}, tr, 1.f, 1.f); if (grid && subgrid) openvdb::tools::csgUnion(*grid, *subgrid); else if (subgrid) grid = std::move(subgrid); @@ -71,7 +71,7 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set & mesh, if(meshparts.empty()) { // Splitting failed, fall back to hollow the original mesh grid = openvdb::tools::meshToVolume( - TriangleMeshDataAdapter{mesh}, tr); + TriangleMeshDataAdapter{mesh}, tr, 1.f, 1.f); } constexpr int DilateIterations = 1; From 39a47e91f72c1cad56803ef93059390857b4e674 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Thu, 7 Apr 2022 16:30:05 +0200 Subject: [PATCH 7/8] Fix failing test for hollowing --- src/libslic3r/SLA/Hollowing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libslic3r/SLA/Hollowing.cpp b/src/libslic3r/SLA/Hollowing.cpp index 4a33dec7d..fe74fe336 100644 --- a/src/libslic3r/SLA/Hollowing.cpp +++ b/src/libslic3r/SLA/Hollowing.cpp @@ -67,7 +67,7 @@ static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh, { double offset = voxel_scale * min_thickness; double D = voxel_scale * closing_dist; - float in_range = /*1.1f * */float(offset + D); + float in_range = 1.1f * float(offset + D); if (ctl.stopcondition()) return {}; else ctl.statuscb(0, L("Hollowing")); From 610e97137354853453150cef3bdf112c31c4bc48 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Mon, 11 Apr 2022 12:26:39 +0200 Subject: [PATCH 8/8] Fix Fix triangle removal issues when using full narrow band of interior --- src/libslic3r/OpenVDBUtils.cpp | 5 ++ src/libslic3r/SLA/Hollowing.cpp | 98 ++++++++++++++++----------------- 2 files changed, 54 insertions(+), 49 deletions(-) diff --git a/src/libslic3r/OpenVDBUtils.cpp b/src/libslic3r/OpenVDBUtils.cpp index c14dc7e63..2c207bb6a 100644 --- a/src/libslic3r/OpenVDBUtils.cpp +++ b/src/libslic3r/OpenVDBUtils.cpp @@ -68,6 +68,11 @@ openvdb::FloatGrid::Ptr mesh_to_grid(const indexed_triangle_set & mesh, else if (subgrid) grid = std::move(subgrid); } + if (meshparts.size() > 1) { + // This is needed to avoid various artefacts on multipart meshes. + // TODO: replace with something faster + grid = openvdb::tools::levelSetRebuild(*grid, 0., 1.f, 1.f); + } if(meshparts.empty()) { // Splitting failed, fall back to hollow the original mesh grid = openvdb::tools::meshToVolume( diff --git a/src/libslic3r/SLA/Hollowing.cpp b/src/libslic3r/SLA/Hollowing.cpp index fe74fe336..8cda341b5 100644 --- a/src/libslic3r/SLA/Hollowing.cpp +++ b/src/libslic3r/SLA/Hollowing.cpp @@ -29,12 +29,10 @@ struct Interior { openvdb::FloatGrid::Ptr gridptr; mutable std::optional accessor; - double closing_distance = 0.; + double iso_surface = 0.; double thickness = 0.; double voxel_scale = 1.; - double nb_in = 3.; // narrow band width inwards - double nb_out = 3.; // narrow band width outwards - // Full narrow band is the sum of the two above values. + double full_narrowb = 2.; void reset_accessor() const // This resets the accessor and its cache // Not a thread safe call! @@ -65,14 +63,16 @@ static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh, double voxel_scale, double closing_dist) { - double offset = voxel_scale * min_thickness; - double D = voxel_scale * closing_dist; + double offset = voxel_scale * min_thickness; + double D = voxel_scale * closing_dist; float in_range = 1.1f * float(offset + D); + auto narrowb = 1.; + float out_range = narrowb; if (ctl.stopcondition()) return {}; else ctl.statuscb(0, L("Hollowing")); - auto gridptr = mesh_to_grid(mesh.its, {}, voxel_scale, 3., in_range); + auto gridptr = mesh_to_grid(mesh.its, {}, voxel_scale, out_range, in_range); assert(gridptr); @@ -85,15 +85,21 @@ static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh, else ctl.statuscb(30, L("Hollowing")); double iso_surface = D; - auto narrowb = 3.; //double(in_range); - gridptr = redistance_grid(*gridptr, -(offset + D), narrowb, narrowb); + if (D > EPSILON) { + in_range = narrowb; + gridptr = redistance_grid(*gridptr, -(offset + D), narrowb, in_range); - constexpr int DilateIterations = 1; + constexpr int DilateIterations = 1; - gridptr = openvdb::tools::dilateSdf( - *gridptr, std::ceil(iso_surface), - openvdb::tools::NN_FACE_EDGE_VERTEX, DilateIterations, - openvdb::tools::FastSweepingDomain::SWEEP_GREATER_THAN_ISOVALUE); + gridptr = openvdb::tools::dilateSdf( + *gridptr, std::ceil(iso_surface), + openvdb::tools::NN_FACE_EDGE_VERTEX, DilateIterations, + openvdb::tools::FastSweepingDomain::SWEEP_GREATER_THAN_ISOVALUE); + + out_range = iso_surface; + } else { + iso_surface = -offset; + } if (ctl.stopcondition()) return {}; else ctl.statuscb(70, L("Hollowing")); @@ -107,11 +113,10 @@ static InteriorPtr generate_interior_verbose(const TriangleMesh & mesh, if (ctl.stopcondition()) return {}; else ctl.statuscb(100, L("Hollowing")); - interior->closing_distance = D; - interior->thickness = offset; + interior->iso_surface = iso_surface; + interior->thickness = offset; interior->voxel_scale = voxel_scale; - interior->nb_in = narrowb; - interior->nb_out = iso_surface; + interior->full_narrowb = out_range + in_range; return interior; } @@ -120,8 +125,8 @@ InteriorPtr generate_interior(const TriangleMesh & mesh, const HollowingConfig &hc, const JobController & ctl) { - static constexpr double MIN_OVERSAMPL = 1.; - static constexpr double MAX_OVERSAMPL = 10.; + static constexpr double MIN_SAMPLES_IN_WALL = 3.5; + static constexpr double MAX_OVERSAMPL = 8.; static constexpr double UNIT_VOLUME = 500000; // empiric // I can't figure out how to increase the grid resolution through openvdb @@ -130,26 +135,25 @@ InteriorPtr generate_interior(const TriangleMesh & mesh, // scales the whole geometry down, and doesn't increase the number of // voxels. // - // the voxel_scale will always reside between MIN_OVERSAMPL and - // a dynamically derived maximum (based on the model volume) - // which is always less than MAX_OVERSAMPL. The quality parameter will - // control the actual position of the scaling between this allowed range. - // - // For smaller models, the maximum can get up to MAX_OVERSAMPL - // for bigger models (reference unit volume is VOL_SCALING) the maximum - // is gradually decreased. - double mesh_vol = its_volume(mesh.its); - double sc_divider = std::max(1.0, (mesh_vol / UNIT_VOLUME)); - double max_oversampl_scaled = std::max(MIN_OVERSAMPL, - MAX_OVERSAMPL / sc_divider); - auto voxel_scale = MIN_OVERSAMPL + (max_oversampl_scaled - MIN_OVERSAMPL) * hc.quality; - BOOST_LOG_TRIVIAL(debug) << "Hollowing: max oversampl will be: " << max_oversampl_scaled; - BOOST_LOG_TRIVIAL(debug) << "Hollowing: voxel scale will be: " << voxel_scale; - BOOST_LOG_TRIVIAL(debug) << "Hollowing: mesh volume is: " << mesh_vol; + // First an allowed range for voxel scale is determined from an initial + // range of . The final voxel scale is + // then chosen from this range using the 'quality:<0, 1>' parameter. + // The minimum can be lowered if the wall thickness is great enough and + // the maximum is lowered if the model volume very big. + double mesh_vol = its_volume(mesh.its); + double sc_divider = std::max(1.0, (mesh_vol / UNIT_VOLUME)); + double min_oversampl = std::max(MIN_SAMPLES_IN_WALL / hc.min_thickness, 1.); + double max_oversampl_scaled = std::max(min_oversampl, MAX_OVERSAMPL / sc_divider); + auto voxel_scale = min_oversampl + (max_oversampl_scaled - min_oversampl) * hc.quality; - InteriorPtr interior = - generate_interior_verbose(mesh, ctl, hc.min_thickness, voxel_scale, - hc.closing_distance); + BOOST_LOG_TRIVIAL(debug) << "Hollowing: max oversampl will be: " << max_oversampl_scaled; + BOOST_LOG_TRIVIAL(debug) << "Hollowing: voxel scale will be: " << voxel_scale; + BOOST_LOG_TRIVIAL(debug) << "Hollowing: mesh volume is: " << mesh_vol; + + InteriorPtr interior = generate_interior_verbose(mesh, ctl, + hc.min_thickness, + voxel_scale, + hc.closing_distance); if (interior && !interior->mesh.empty()) { @@ -365,22 +369,18 @@ struct TriangleBubble { Vec3f center; double R; }; static double get_distance(const TriangleBubble &b, const Interior &interior) { double R = b.R * interior.voxel_scale; - double D = get_distance_raw(b.center, interior); + double D = 2. * R; + double Dst = get_distance_raw(b.center, interior); - return (D > 0. && R >= interior.nb_out) || - (D < 0. && R >= interior.nb_in) || - ((D - R) < 0. && 2 * R > interior.thickness) ? + return D > interior.full_narrowb || + ((Dst - R) < 0. && 2 * R > interior.thickness) ? std::nan("") : - // FIXME: Adding interior.voxel_scale is a compromise supposed - // to prevent the deletion of the triangles forming the interior - // itself. This has a side effect that a small portion of the - // bad triangles will still be visible. - D - interior.closing_distance /*+ 2 * interior.voxel_scale*/; + Dst - interior.iso_surface; } double get_distance(const Vec3f &p, const Interior &interior) { - double d = get_distance_raw(p, interior) - interior.closing_distance; + double d = get_distance_raw(p, interior) - interior.iso_surface; return d / interior.voxel_scale; }