diff --git a/src/libslic3r/OpenVDBUtils.cpp b/src/libslic3r/OpenVDBUtils.cpp index 08c69bdb5d..53f9d5ae9f 100644 --- a/src/libslic3r/OpenVDBUtils.cpp +++ b/src/libslic3r/OpenVDBUtils.cpp @@ -158,20 +158,35 @@ inline void _scale(S s, sla::Contour3D &m) for (auto &p : m.points) p *= s; } +static void filter_grid(openvdb::FloatGrid &grid, double scale, double gain) +{ + static const double ROUNDNESS_COEFF = 1.; + + // Filtering: + if (gain > 0.) { + double rounding = ROUNDNESS_COEFF * gain; + int width = int(rounding * scale); + int count = 1; + openvdb::tools::Filter{grid}.gaussian(width, count); + } +} + template remove_cvref_t _hollowed_interior(Mesh &&mesh, double min_thickness, - int oversampling, + double accuracy, double smoothing) { using MMesh = remove_cvref_t; MMesh imesh{std::forward(mesh)}; + static const double ACCURACY_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 = double(oversampling); + auto scale = (1.0 + ACCURACY_COEFF * accuracy); // max 8x upscale, min is native voxel size _scale(scale, imesh); @@ -186,10 +201,7 @@ remove_cvref_t _hollowed_interior(Mesh &&mesh, return MMesh{}; } - // Filtering: - int width = int(smoothing * scale); - int count = 1; - openvdb::tools::Filter{*gridptr}.gaussian(width, count); + filter_grid(*gridptr, scale, smoothing); double iso_surface = -offset; double adaptivity = 0.; @@ -202,10 +214,10 @@ remove_cvref_t _hollowed_interior(Mesh &&mesh, TriangleMesh hollowed_interior(const TriangleMesh &mesh, double min_thickness, - int oversampling, + double accuracy, double smoothing) { - return _hollowed_interior(mesh, min_thickness, oversampling, smoothing); + return _hollowed_interior(mesh, min_thickness, accuracy, smoothing); } } // namespace Slic3r diff --git a/src/libslic3r/OpenVDBUtils.hpp b/src/libslic3r/OpenVDBUtils.hpp index 8e55300bd2..95b95db7ce 100644 --- a/src/libslic3r/OpenVDBUtils.hpp +++ b/src/libslic3r/OpenVDBUtils.hpp @@ -18,16 +18,13 @@ TriangleMesh volumeToMesh(const openvdb::FloatGrid &grid, double adaptivity = 0.0, bool relaxDisorientedTriangles = true); -sla::Contour3D hollowed_interior(sla::Contour3D&& mesh, double min_thickness); -sla::Contour3D hollowed_interior(sla::Contour3D& mesh, double min_thickness); - // 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. // TODO: The thicknes is not strictly maintained due to the used gaussian filter TriangleMesh hollowed_interior(const TriangleMesh &mesh, double min_thickness, - int oversampling = 3, double smoothing = 0.5); + double accuracy = 0.5, double smoothing = 0.5); } // namespace Slic3r diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 4cfd81bc55..e621d4b340 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2846,6 +2846,25 @@ void PrintConfigDef::init_sla_params() def->min = 1; def->mode = comSimple; def->set_default_value(new ConfigOptionFloat(4)); + + def = this->add("hollowing_accuracy", coFloat); + def->label = L("Hollowing accuracy"); + def->category = L("Hollowing"); + def->tooltip = L("Performance vs accuracy of calculation. Lower values may produce unwanted artifacts."); + def->min = 0; + def->max = 1; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloat(0.5)); + + def = this->add("hollowing_smoothness", coFloat); + def->label = L("Hollowing smoothness"); + 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->min = 0; + def->max = 1; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloat(0.5)); } 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 6bcc3f9ad2..d07999c886 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1097,6 +1097,13 @@ public: // resulting walls may be thicker due to smoothing out fine cavities where // resin could stuck. ConfigOptionFloat hollowing_min_thickness; + + // Indirectly controls the voxel size (resolution) used by openvdb + ConfigOptionFloat hollowing_accuracy; + + // Indirectly controls the amount of filtering used to blur geometry + // features in the created cavity. + ConfigOptionFloat hollowing_smoothness; protected: void initialize(StaticCacheBase &cache, const char *base_ptr) @@ -1136,6 +1143,8 @@ protected: OPT_PTR(pad_object_connector_penetration); OPT_PTR(hollowing_enable); OPT_PTR(hollowing_min_thickness); + OPT_PTR(hollowing_accuracy); + OPT_PTR(hollowing_smoothness); } }; diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 2e8a704005..d2200bcfb2 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -776,9 +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_accuracy.getFloat(); + double blur = po.m_config.hollowing_smoothness.getFloat(); po.m_hollowing_data->interior = - hollowed_interior(po.transformed_mesh(), thickness, 4, 0.5); + hollowed_interior(po.transformed_mesh(), thickness, accuracy, blur); if (po.m_hollowing_data->interior.empty()) BOOST_LOG_TRIVIAL(warning) << "Hollowed interior is empty!"; @@ -1752,7 +1753,10 @@ bool SLAPrintObject::invalidate_state_by_config_options(const std::vectormerge(*m_mesh); m_cavity_mesh.get()->require_shared_vertices(); @@ -692,7 +694,7 @@ RENDER_AGAIN: if (m_editing_mode) { if (m_imgui->button(m_desc.at("hollow"))) { - hollow_mesh(m_offset); + hollow_mesh(); } float diameter_upper_cap = static_cast(wxGetApp().preset_bundle->sla_prints.get_edited_preset().config.option("support_pillar_diameter"))->value; @@ -748,12 +750,22 @@ RENDER_AGAIN: remove_all = m_imgui->button(m_desc.at("remove_all")); m_imgui->disabled_end(); - m_imgui->text(" "); // vertical gap +// m_imgui->text(" "); // vertical gap m_imgui->text("Offset: "); ImGui::SameLine(); ImGui::SliderFloat(" ", &m_offset, 0.f, 10.f, "%.1f"); + + // TODO: only in expert mode: + m_imgui->text("Accuracy: "); + ImGui::SameLine(); + ImGui::SliderFloat(" ", &m_accuracy, 0.f, 1.f, "%.1f"); + + // TODO: only in expert mode: + m_imgui->text("Smoothness: "); + ImGui::SameLine(); + ImGui::SliderFloat(" ", &m_smoothness, 0.f, 1.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 ba950594a2..0cf1e1ecb1 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.hpp @@ -92,7 +92,7 @@ private: void render_clipping_plane(const Selection& selection) const; bool is_mesh_update_necessary() const; void update_mesh(); - void hollow_mesh(float offset = 2.f); + void hollow_mesh(); bool unsaved_changes() const; const TriangleMesh* mesh() const; @@ -108,14 +108,19 @@ private: mutable std::vector m_editing_cache; // a support point and whether it is currently selected std::vector m_normal_cache; // to restore after discarding changes or undo/redo - float m_offset = 2.f; + float m_offset = 2.0f; 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 edbb5fb750..483bff8e55 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -498,6 +498,8 @@ const std::vector& Preset::sla_print_options() "pad_object_connector_penetration", "hollowing_enable", "hollowing_min_thickness", + "hollowing_accuracy", + "hollowing_smoothness", "output_filename_format", "default_sla_print_profile", "compatible_printers", diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 22c4bfb9bf..d20e0ee6c8 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -3568,6 +3568,8 @@ void TabSLAPrint::build() optgroup = page->new_optgroup(_(L("Hollowing"))); optgroup->append_single_option_line("hollowing_enable"); optgroup->append_single_option_line("hollowing_min_thickness"); + optgroup->append_single_option_line("hollowing_accuracy"); + optgroup->append_single_option_line("hollowing_smoothness"); page = add_options_page(_(L("Advanced")), "wrench"); optgroup = page->new_optgroup(_(L("Slicing")));