From ac8eab5fa8e6c38faf788349bcb4f0f707d6bbbe Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 8 Nov 2019 16:51:43 +0100 Subject: Enhanced hollowing scheme, closing distance working as expected. --- src/libslic3r/OpenVDBUtils.cpp | 109 +++++---------------------- src/libslic3r/OpenVDBUtils.hpp | 33 ++++++--- src/libslic3r/PrintConfig.cpp | 10 +-- src/libslic3r/PrintConfig.hpp | 9 +-- src/libslic3r/SLA/Hollowing.cpp | 127 ++++++++++++++++++++++++-------- src/libslic3r/SLAPrint.cpp | 8 +- src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp | 8 +- src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp | 9 +-- src/slic3r/GUI/Preset.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 2 +- 10 files changed, 156 insertions(+), 161 deletions(-) diff --git a/src/libslic3r/OpenVDBUtils.cpp b/src/libslic3r/OpenVDBUtils.cpp index 91ccdd5c4..c76bad96c 100644 --- a/src/libslic3r/OpenVDBUtils.cpp +++ b/src/libslic3r/OpenVDBUtils.cpp @@ -2,9 +2,9 @@ #include "OpenVDBUtils.hpp" #include #include -#include -#include -#include "MTUtils.hpp" +#include + +//#include "MTUtils.hpp" namespace Slic3r { @@ -58,7 +58,7 @@ void Contour3DDataAdapter::getIndexSpacePoint(size_t n, // docs say it should be called ones. It does a mutex lock-unlock sequence all // even if was called previously. -openvdb::FloatGrid::Ptr meshToVolume(const TriangleMesh &mesh, +openvdb::FloatGrid::Ptr mesh_to_grid(const TriangleMesh &mesh, const openvdb::math::Transform &tr, float exteriorBandWidth, float interiorBandWidth, @@ -70,7 +70,7 @@ openvdb::FloatGrid::Ptr meshToVolume(const TriangleMesh &mesh, interiorBandWidth, flags); } -static openvdb::FloatGrid::Ptr meshToVolume(const sla::Contour3D &mesh, +openvdb::FloatGrid::Ptr mesh_to_grid(const sla::Contour3D &mesh, const openvdb::math::Transform &tr, float exteriorBandWidth, float interiorBandWidth, @@ -82,13 +82,8 @@ static openvdb::FloatGrid::Ptr meshToVolume(const sla::Contour3D &mesh, flags); } -inline Vec3f to_vec3f(const openvdb::Vec3s &v) { return Vec3f{v.x(), v.y(), v.z()}; } -inline Vec3d to_vec3d(const openvdb::Vec3s &v) { return to_vec3f(v).cast(); } -inline Vec3i to_vec3i(const openvdb::Vec3I &v) { return Vec3i{int(v[0]), int(v[1]), int(v[2])}; } -inline Vec4i to_vec4i(const openvdb::Vec4I &v) { return Vec4i{int(v[0]), int(v[1]), int(v[2]), int(v[3])}; } - template -sla::Contour3D __volumeToMesh(const Grid &grid, +sla::Contour3D _volumeToMesh(const Grid &grid, double isovalue, double adaptivity, bool relaxDisorientedTriangles) @@ -114,97 +109,27 @@ sla::Contour3D __volumeToMesh(const Grid &grid, return ret; } -template inline -Mesh _volumeToMesh(const openvdb::FloatGrid &grid, - double isovalue = 0.0, - double adaptivity = 0.0, - bool relaxDisorientedTriangles = true); - -template<> inline -TriangleMesh _volumeToMesh(const openvdb::FloatGrid &grid, +TriangleMesh grid_to_mesh(const openvdb::FloatGrid &grid, double isovalue, double adaptivity, bool relaxDisorientedTriangles) { - return to_triangle_mesh(__volumeToMesh(grid, isovalue, adaptivity, - relaxDisorientedTriangles)); -} - -template<> inline -sla::Contour3D _volumeToMesh(const openvdb::FloatGrid &grid, - double isovalue, - double adaptivity, - bool relaxDisorientedTriangles) -{ - return __volumeToMesh(grid, isovalue, adaptivity, - relaxDisorientedTriangles); + return to_triangle_mesh( + _volumeToMesh(grid, isovalue, adaptivity, relaxDisorientedTriangles)); } -TriangleMesh volumeToMesh(const openvdb::FloatGrid &grid, - double isovalue, - double adaptivity, - bool relaxDisorientedTriangles) +sla::Contour3D grid_to_contour3d(const openvdb::FloatGrid &grid, + double isovalue, + double adaptivity, + bool relaxDisorientedTriangles) { - return _volumeToMesh(grid, isovalue, adaptivity, - relaxDisorientedTriangles); -} - -template> -inline void _scale(S s, TriangleMesh &m) { m.scale(float(s)); } - -template> -inline void _scale(S s, sla::Contour3D &m) -{ - for (auto &p : m.points) p *= s; -} - -template -remove_cvref_t _hollowed_interior(Mesh &&mesh, - double min_thickness, - double quality, - HollowingFilter filt) -{ - using MMesh = remove_cvref_t; - MMesh imesh{std::forward(mesh)}; - - static const double QUALITY_COEFF = 7.; - - // 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 scaled - // down. Voxels have a unit size. If I set voxelSize smaller, it scales - // the whole geometry down, and doesn't increase the number of voxels. - auto scale = (1.0 + QUALITY_COEFF * quality); // max 8x upscale, min is native voxel size - - _scale(scale, imesh); - - double offset = scale * min_thickness; - float range = float(std::max(2 * offset, scale)); - auto gridptr = meshToVolume(imesh, {}, 0.1f * float(offset), range); - - assert(gridptr); - - if (!gridptr) { - BOOST_LOG_TRIVIAL(error) << "Returned OpenVDB grid is NULL"; - return MMesh{}; - } - - if (filt) filt(*gridptr, min_thickness, scale); - - double iso_surface = -offset; - double adaptivity = 0.; - auto omesh = _volumeToMesh(*gridptr, iso_surface, adaptivity); - - _scale(1. / scale, omesh); - - return omesh; + return _volumeToMesh(grid, isovalue, adaptivity, + relaxDisorientedTriangles); } -TriangleMesh hollowed_interior(const TriangleMesh &mesh, - double min_thickness, - double quality, - HollowingFilter filt) +openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid, double iso, double er, double ir) { - return _hollowed_interior(mesh, min_thickness, quality, filt); + return openvdb::tools::levelSetRebuild(grid, float(iso), float(er), float(ir)); } } // namespace Slic3r diff --git a/src/libslic3r/OpenVDBUtils.hpp b/src/libslic3r/OpenVDBUtils.hpp index bd52e81ee..151647bfc 100644 --- a/src/libslic3r/OpenVDBUtils.hpp +++ b/src/libslic3r/OpenVDBUtils.hpp @@ -7,26 +7,37 @@ namespace Slic3r { -openvdb::FloatGrid::Ptr meshToVolume(const TriangleMesh & mesh, +inline Vec3f to_vec3f(const openvdb::Vec3s &v) { return Vec3f{v.x(), v.y(), v.z()}; } +inline Vec3d to_vec3d(const openvdb::Vec3s &v) { return to_vec3f(v).cast(); } +inline Vec3i to_vec3i(const openvdb::Vec3I &v) { return Vec3i{int(v[0]), int(v[1]), int(v[2])}; } +inline Vec4i to_vec4i(const openvdb::Vec4I &v) { return Vec4i{int(v[0]), int(v[1]), int(v[2]), int(v[3])}; } + +openvdb::FloatGrid::Ptr mesh_to_grid(const TriangleMesh & mesh, + const openvdb::math::Transform &tr = {}, + float exteriorBandWidth = 3.0f, + float interiorBandWidth = 3.0f, + int flags = 0); + +openvdb::FloatGrid::Ptr mesh_to_grid(const sla::Contour3D & mesh, const openvdb::math::Transform &tr = {}, float exteriorBandWidth = 3.0f, float interiorBandWidth = 3.0f, int flags = 0); -TriangleMesh volumeToMesh(const openvdb::FloatGrid &grid, +sla::Contour3D grid_to_contour3d(const openvdb::FloatGrid &grid, + double isovalue, + double adaptivity, + bool relaxDisorientedTriangles = true); + +TriangleMesh grid_to_mesh(const openvdb::FloatGrid &grid, double isovalue = 0.0, double adaptivity = 0.0, bool relaxDisorientedTriangles = true); -using HollowingFilter = std::function; - -// Generate an interior for any solid geometry maintaining a given minimum -// wall thickness. The returned mesh has triangles with normals facing inside -// the mesh so the result can be directly merged with the input to finish the -// hollowing. -TriangleMesh hollowed_interior(const TriangleMesh &mesh, double min_thickness, - double quality = 0.5, - HollowingFilter filt = nullptr); +openvdb::FloatGrid::Ptr redistance_grid(const openvdb::FloatGrid &grid, + double iso, + double ext_range = 3., + double int_range = 3.); } // namespace Slic3r diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 96b84cf81..58212f128 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2856,15 +2856,13 @@ void PrintConfigDef::init_sla_params() def->mode = comExpert; def->set_default_value(new ConfigOptionFloat(0.5)); - def = this->add("hollowing_flatness", coFloat); - def->label = L("Hollowing smoothness"); + def = this->add("hollowing_closing_distance", coFloat); + def->label = L("Hollowing closing distance"); def->category = L("Hollowing"); - def->tooltip = L("The cavity shape is a smoothed version of the outside original shape. " - "Possible values span from 0 to 1 and control the amount of surface smoothing."); + def->tooltip = L(""); def->min = 0; - def->max = 1; def->mode = comExpert; - def->set_default_value(new ConfigOptionFloat(0.5)); + def->set_default_value(new ConfigOptionFloat(2.0)); } void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &value) diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 9ed63e5d4..671a6ce8e 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1100,10 +1100,9 @@ public: // Indirectly controls the voxel size (resolution) used by openvdb ConfigOptionFloat hollowing_quality; - - // Indirectly controls the amount of filtering used to blur geometry - // features in the created cavity. - ConfigOptionFloat hollowing_flatness; + + // Indirectly controls the minimum size of created cavities. + ConfigOptionFloat hollowing_closing_distance; protected: void initialize(StaticCacheBase &cache, const char *base_ptr) @@ -1144,7 +1143,7 @@ protected: OPT_PTR(hollowing_enable); OPT_PTR(hollowing_min_thickness); OPT_PTR(hollowing_quality); - OPT_PTR(hollowing_flatness); + OPT_PTR(hollowing_closing_distance); } }; diff --git a/src/libslic3r/SLA/Hollowing.cpp b/src/libslic3r/SLA/Hollowing.cpp index 430900313..c3993f2c8 100644 --- a/src/libslic3r/SLA/Hollowing.cpp +++ b/src/libslic3r/SLA/Hollowing.cpp @@ -1,55 +1,122 @@ -#include "Hollowing.hpp" -#include -#include -#include #include +//#include +#include + +#include "Hollowing.hpp" +#include + namespace Slic3r { namespace sla { -namespace { +//namespace { + +//void filter_grid_sla(openvdb::FloatGrid::Ptr &grid, double scale, double /*thickness*/, double flatness, double closing_dist) +//{ +// static const double ROUNDNESS_COEFF = 1.; + +// // Filtering: +// if (flatness > 0.) { +// double rounding = ROUNDNESS_COEFF * flatness; +// int width = int(rounding * scale); +// int count = 1; +// openvdb::tools::Filter{*grid}.gaussian(width, count); +// } +//} + +//} + +template> +inline void _scale(S s, TriangleMesh &m) { m.scale(float(s)); } -void filter_grid_sla(openvdb::FloatGrid &grid, double scale, double /*thickness*/, double flatness) +template> +inline void _scale(S s, sla::Contour3D &m) { - static const double ROUNDNESS_COEFF = 1.; - - // Filtering: - if (flatness > 0.) { - double rounding = ROUNDNESS_COEFF * flatness; - int width = int(rounding * scale); - int count = 1; - openvdb::tools::Filter{grid}.gaussian(width, count); - } + for (auto &p : m.points) p *= s; } -// openvdb::tools::levelSetRebuild(grid, -float(thickness * 2)); -// filter_grid_sla(grid, scale, thickness, flatness); -// openvdb::tools::levelSetRebuild(grid, float(thickness)); +template +remove_cvref_t _grid_to_mesh(const openvdb::FloatGrid &grid, + double isosurf, + double adapt); + +template<> +TriangleMesh _grid_to_mesh(const openvdb::FloatGrid &grid, + double isosurf, + double adapt) +{ + return grid_to_mesh(grid, isosurf, adapt); +} +template<> +sla::Contour3D _grid_to_mesh(const openvdb::FloatGrid &grid, + double isosurf, + double adapt) +{ + return grid_to_contour3d(grid, isosurf, adapt); +} -void redist_grid_sla(openvdb::FloatGrid &grid, double scale, double thickness, double flatness) +template +remove_cvref_t _generate_interior(Mesh &&mesh, + double min_thickness, + double voxel_scale, + double closing_dist) { -// openvdb::tools::levelSetRebuild(grid, -float(scale * thickness)); +// namespace plc = std::placeholders; +// auto filt = std::bind(redist_grid_sla, plc::_1, plc::_2, plc::_3, flatness, closing_dist); +// return hollowed_interior(mesh, min_thickness, quality, filt); + + using MMesh = remove_cvref_t; + MMesh imesh{std::forward(mesh)}; + _scale(voxel_scale, imesh); - openvdb::tools::LevelSetFilter filt{grid}; + 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); + auto gridptr = mesh_to_grid(imesh, {}, out_range, in_range); -// filt.gaussian(int(flatness * scale)); + assert(gridptr); -// openvdb::tools::levelSetRebuild(grid, float(scale * thickness)); - //grid = openvdb::tools::topologyToLevelSet(grid); -} - + if (!gridptr) { + BOOST_LOG_TRIVIAL(error) << "Returned OpenVDB grid is NULL"; + return MMesh{}; + } + + if (closing_dist > .0) { + gridptr = redistance_grid(*gridptr, -(offset + D), double(in_range)); + } else { + D = -offset; + } + +// openvdb::tools::Filter filt{*gridptr}; +// filt.offset(float(offset + D)); + + double iso_surface = D; + double adaptivity = 0.; + auto omesh = _grid_to_mesh(*gridptr, iso_surface, adaptivity); + + _scale(1. / voxel_scale, omesh); + + return omesh; } TriangleMesh generate_interior(const TriangleMesh &mesh, double min_thickness, double quality, - double flatness) + double closing_dist) { - namespace plc = std::placeholders; - auto filt = std::bind(filter_grid_sla, plc::_1, plc::_2, plc::_3, flatness); - return hollowed_interior(mesh, min_thickness, quality, filt); + static const double MAX_OVERSAMPL = 7.; + + // 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 scaled + // down. Voxels have a unit size. If I set voxelSize smaller, it scales + // the whole geometry down, and doesn't increase the number of voxels. + // + // max 8x upscale, min is native voxel size + auto voxel_scale = (1.0 + MAX_OVERSAMPL * quality); + return _generate_interior(mesh, min_thickness, voxel_scale, closing_dist); } }} // namespace Slic3r::sla diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index b150a4f76..3273cbcfe 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -776,10 +776,10 @@ void SLAPrint::process() po.m_hollowing_data.reset(new SLAPrintObject::HollowingData()); double thickness = po.m_config.hollowing_min_thickness.getFloat(); - double accuracy = po.m_config.hollowing_quality.getFloat(); - double blur = po.m_config.hollowing_flatness.getFloat(); + double quality = po.m_config.hollowing_quality.getFloat(); + double closing_d = po.m_config.hollowing_closing_distance.getFloat(); po.m_hollowing_data->interior = - generate_interior(po.transformed_mesh(), thickness, accuracy, blur); + generate_interior(po.transformed_mesh(), thickness, quality, closing_d); if (po.m_hollowing_data->interior.empty()) BOOST_LOG_TRIVIAL(warning) << "Hollowed interior is empty!"; @@ -1755,7 +1755,7 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vectortext(" "); // vertical gap - m_imgui->text("Offset: "); ImGui::SameLine(); ImGui::SliderFloat(" ", &m_offset, 0.f, 10.f, "%.1f"); @@ -763,10 +762,9 @@ RENDER_AGAIN: ImGui::SameLine(); ImGui::SliderFloat(" ", &m_accuracy, 0.f, 1.f, "%.1f"); - // TODO: only in expert mode: - m_imgui->text("Smoothness: "); + m_imgui->text("Closing distance: "); ImGui::SameLine(); - ImGui::SliderFloat(" ", &m_smoothness, 0.f, 1.f, "%.1f"); + ImGui::SliderFloat(" ", &m_closing_d, 0.f, 20.f, "%.1f"); } else { // not in editing mode: m_imgui->text(m_desc.at("minimal_distance")); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp index 0cf1e1ecb..642f7f5a2 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp @@ -109,18 +109,15 @@ private: std::vector m_normal_cache; // to restore after discarding changes or undo/redo float m_offset = 2.0f; - + float m_accuracy = 0.5f; + float m_closing_d = 2.f; + float m_clipping_plane_distance = 0.f; std::unique_ptr m_clipping_plane; - float m_accuracy = 0.5f; - // This map holds all translated description texts, so they can be easily referenced during layout calculations // etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect. std::map m_desc; - - - float m_smoothness = 0.5f; GLSelectionRectangle m_selection_rectangle; diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 6f511fdec..3b5a2f985 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -499,7 +499,7 @@ const std::vector& Preset::sla_print_options() "hollowing_enable", "hollowing_min_thickness", "hollowing_quality", - "hollowing_flatness", + "hollowing_closing_distance", "output_filename_format", "default_sla_print_profile", "compatible_printers", diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 333384802..6f17abea4 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -3569,7 +3569,7 @@ void TabSLAPrint::build() optgroup->append_single_option_line("hollowing_enable"); optgroup->append_single_option_line("hollowing_min_thickness"); optgroup->append_single_option_line("hollowing_quality"); - optgroup->append_single_option_line("hollowing_flatness"); + optgroup->append_single_option_line("hollowing_closing_distance"); page = add_options_page(_(L("Advanced")), "wrench"); optgroup = page->new_optgroup(_(L("Slicing"))); -- cgit v1.2.3