From 3d16c7f4c8d961bcc50692b7b6d2c9b6770ec62a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CF=80=C2=B2?= Date: Fri, 25 Jul 2025 10:36:18 +0300 Subject: [PATCH] Feature: Fuzzy Skin Extrusion Mode (#9878) * Feature: Fuzzy Skin Extrusion Mode This extension allows you to add new features to the fuzzy skin generator. * Add auto switch to Arachne mode * Move dialog to `update_print_fff_config` and update how `is_msg_dlg_already_exist` is used --------- Co-authored-by: Noisyfox --- src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp | 21 +++++++++++-- src/libslic3r/PerimeterGenerator.hpp | 4 ++- src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 31 ++++++++++++++++++- src/libslic3r/PrintConfig.hpp | 9 ++++++ src/libslic3r/PrintObject.cpp | 1 + src/slic3r/GUI/ConfigManipulation.cpp | 19 +++++++++++- src/slic3r/GUI/Tab.cpp | 1 + 8 files changed, 81 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp b/src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp index a79220951e..66fc90dc99 100644 --- a/src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp +++ b/src/libslic3r/Feature/FuzzySkin/FuzzySkin.cpp @@ -116,6 +116,7 @@ void fuzzy_extrusion_line(Arachne::ExtrusionJunctions& ext_lines, coordf_t slice const double min_dist_between_points = cfg.point_distance * 3. / 4.; // hardcoded: the point distance may vary between 3/4 and 5/4 the supplied value const double range_random_point_dist = cfg.point_distance / 2.; + const double min_extrusion_width = 0.01; // workaround for many print options. Need overwrite formula with the layer height parameter. The width must more than >>> layer_height * (1 - 0.25 * PI) * 1.05 <<< (last num is the coeff of overlay error case) double dist_left_over = random_value() * (min_dist_between_points / 2.); // the distance to be traversed on the line before making the first new point auto* p0 = &ext_lines.front(); @@ -134,7 +135,18 @@ void fuzzy_extrusion_line(Arachne::ExtrusionJunctions& ext_lines, coordf_t slice for (; p0pa_dist < p0p1_size; p0pa_dist += min_dist_between_points + random_value() * range_random_point_dist) { Point pa = p0->p + (p0p1 * (p0pa_dist / p0p1_size)).cast(); double r = noise->GetValue(unscale_(pa.x()), unscale_(pa.y()), slice_z) * cfg.thickness; - out.emplace_back(pa + (perp(p0p1).cast().normalized() * r).cast(), p1.w, p1.perimeter_index); + switch (cfg.mode) { //the curly code for testing + case FuzzySkinMode::Displacement : + out.emplace_back(pa + (perp(p0p1).cast().normalized() * r).cast(), p1.w, p1.perimeter_index); + break; + case FuzzySkinMode::Extrusion : + out.emplace_back(pa, std::max(p1.w + r + min_extrusion_width, min_extrusion_width), p1.perimeter_index); + break; + case FuzzySkinMode::Combined : + double rad = std::max(p1.w + r + min_extrusion_width, min_extrusion_width); + out.emplace_back(pa + (perp(p0p1).cast().normalized() * ((rad - p1.w) / 2)).cast(), rad, p1.perimeter_index); //0.05 - minimum width of extruded line + break; + } } dist_left_over = p0pa_dist - p0p1_size; p0 = &p1; @@ -148,8 +160,10 @@ void fuzzy_extrusion_line(Arachne::ExtrusionJunctions& ext_lines, coordf_t slice --point_idx; } - if (ext_lines.back().p == ext_lines.front().p) // Connect endpoints. + if (ext_lines.back().p == ext_lines.front().p) { // Connect endpoints. out.front().p = out.back().p; + out.front().w = out.back().w; + } if (out.size() >= 3) ext_lines = std::move(out); @@ -171,7 +185,8 @@ void group_region_by_fuzzify(PerimeterGenerator& g) region_config.fuzzy_skin_noise_type, region_config.fuzzy_skin_scale, region_config.fuzzy_skin_octaves, - region_config.fuzzy_skin_persistence}; + region_config.fuzzy_skin_persistence, + region_config.fuzzy_skin_mode}; auto& surfaces = regions[cfg]; for (const auto& surface : region->slices.surfaces) { surfaces.push_back(&surface); diff --git a/src/libslic3r/PerimeterGenerator.hpp b/src/libslic3r/PerimeterGenerator.hpp index 0787e952fa..74be04294e 100644 --- a/src/libslic3r/PerimeterGenerator.hpp +++ b/src/libslic3r/PerimeterGenerator.hpp @@ -20,6 +20,7 @@ struct FuzzySkinConfig double noise_scale; int noise_octaves; double noise_persistence; + FuzzySkinMode mode; bool operator==(const FuzzySkinConfig& r) const { @@ -30,7 +31,8 @@ struct FuzzySkinConfig && noise_type == r.noise_type && noise_scale == r.noise_scale && noise_octaves == r.noise_octaves - && noise_persistence == r.noise_persistence; + && noise_persistence == r.noise_persistence + && mode == r.mode; } bool operator!=(const FuzzySkinConfig& r) const { return !(*this == r); } diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 3ee5733929..5cc4c23150 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -791,7 +791,7 @@ static std::vector s_Preset_print_options { "ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing", "ironing_angle", "ironing_inset", "support_ironing", "support_ironing_pattern", "support_ironing_flow", "support_ironing_spacing", "max_travel_detour_distance", - "fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_distance", "fuzzy_skin_first_layer", "fuzzy_skin_noise_type", "fuzzy_skin_scale", "fuzzy_skin_octaves", "fuzzy_skin_persistence", + "fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_distance", "fuzzy_skin_first_layer", "fuzzy_skin_noise_type", "fuzzy_skin_mode", "fuzzy_skin_scale", "fuzzy_skin_octaves", "fuzzy_skin_persistence", "max_volumetric_extrusion_rate_slope", "max_volumetric_extrusion_rate_slope_segment_length","extrusion_rate_smoothing_external_perimeter_only", "inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed", "top_surface_speed", "support_speed", "support_object_xy_distance", "support_object_first_layer_gap", "support_interface_speed", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index d22f570784..7dcb83dd66 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -118,7 +118,6 @@ static t_config_enum_values s_keys_map_GCodeFlavor { }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(GCodeFlavor) - static t_config_enum_values s_keys_map_FuzzySkinType { { "none", int(FuzzySkinType::None) }, { "external", int(FuzzySkinType::External) }, @@ -136,6 +135,13 @@ static t_config_enum_values s_keys_map_NoiseType { }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(NoiseType) +static t_config_enum_values s_keys_map_FuzzySkinMode { + { "displacement", int(FuzzySkinMode::Displacement) }, + { "extrusion", int(FuzzySkinMode::Extrusion) }, + { "combined", int(FuzzySkinMode::Combined)} +}; +CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(FuzzySkinMode) + static t_config_enum_values s_keys_map_InfillPattern { { "monotonic", ipMonotonic }, { "monotonicline", ipMonotonicLine }, @@ -2826,6 +2832,29 @@ void PrintConfigDef::init_fff_params() def->mode = comSimple; def->set_default_value(new ConfigOptionBool(0)); + def = this->add("fuzzy_skin_mode", coEnum); + def->label = L("Fuzzy skin generator mode"); + def->category = L("Others"); + def->tooltip = L("Fuzzy skin generation mode. Works only with Arachne!\n" + "Displacement: Сlassic mode when the pattern is formed by shifting the nozzle sideways from the original path.\n" + "Extrusion: The mode when the pattern formed by the amount of extruded plastic. " + "This is the fast and straight algorithm without unnecessary nozzle shake that gives a smooth pattern. " + "But it is more useful for forming loose walls in the entire they array.\n" + "Combined: Joint mode [Displacement] + [Extrusion]. The appearance of the walls is similar to [Displacement] Mode, but it leaves no pores between the perimeters.\n\n" + "Attention! The [Extrusion] and [Combined] modes works only the fuzzy_skin_thickness parameter not more than the thickness of printed loop." + "At the same time, the width of the extrusion for a particular layer should also not be below a certain level. " + "It is usually equal 15-25%% of a layer height. Therefore, the maximum fuzzy skin thickness with a perimeter width of 0.4 mm and a layer height of 0.2 mm will be 0.4-(0.2*0.25)=±0.35mm! " + "If you enter a higher parameter than this, the error Flow::spacing() will displayed, and the model will not be sliced. You can choose this number until this error is repeated." ); + def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); + def->enum_values.push_back("displacement"); + def->enum_values.push_back("extrusion"); + def->enum_values.push_back("combined"); + def->enum_labels.push_back(L("Displacement")); + def->enum_labels.push_back(L("Extrusion")); + def->enum_labels.push_back(L("Combined")); + def->mode = comSimple; + def->set_default_value(new ConfigOptionEnum(FuzzySkinMode::Displacement)); + def = this->add("fuzzy_skin_noise_type", coEnum); def->label = L("Fuzzy skin noise type"); def->category = L("Others"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 4a1f5fb420..bea60fc749 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -34,6 +34,7 @@ enum GCodeFlavor : unsigned char { gcfSmoothie, gcfNoExtrusion }; + enum class FuzzySkinType { None, External, @@ -41,6 +42,12 @@ enum class FuzzySkinType { AllWalls, }; +enum class FuzzySkinMode { + Displacement, + Extrusion, + Combined, +}; + enum class NoiseType { Classic, Perlin, @@ -440,6 +447,7 @@ static std::string get_bed_temp_1st_layer_key(const BedType type) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(PrinterTechnology) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(GCodeFlavor) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(FuzzySkinType) +CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(FuzzySkinMode) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(NoiseType) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(InfillPattern) CONFIG_OPTION_ENUM_DECLARE_STATIC_MAPS(IroningType) @@ -980,6 +988,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, fuzzy_skin_point_distance)) ((ConfigOptionBool, fuzzy_skin_first_layer)) ((ConfigOptionEnum, fuzzy_skin_noise_type)) + ((ConfigOptionEnum, fuzzy_skin_mode)) ((ConfigOptionFloat, fuzzy_skin_scale)) ((ConfigOptionInt, fuzzy_skin_octaves)) ((ConfigOptionFloat, fuzzy_skin_persistence)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index b07c11163f..c84a265610 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1133,6 +1133,7 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "fuzzy_skin_thickness" || opt_key == "fuzzy_skin_point_distance" || opt_key == "fuzzy_skin_first_layer" + || opt_key == "fuzzy_skin_mode" || opt_key == "fuzzy_skin_noise_type" || opt_key == "fuzzy_skin_scale" || opt_key == "fuzzy_skin_octaves" diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index f8bc5393b9..01417fcbca 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -486,7 +486,24 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con apply(config, &new_conf); is_msg_dlg_already_exist = false; } - + + bool have_arachne = config->opt_enum("wall_generator") == PerimeterGeneratorType::Arachne; + if (config->opt_enum("fuzzy_skin_mode") != FuzzySkinMode::Displacement && !have_arachne) { + wxString msg_text = _(L("Both [Extrusion] and [Combined] modes of Fuzzy Skin require the Arachne Wall Generator to be enabled.")); + msg_text += "\n\n" + _(L("Change these settings automatically?\n" + "Yes - Enable Arachne Wall Generator\n" + "No - Disable Arachne Wall Generator and set [Displacement] mode of the Fuzzy Skin")); + MessageDialog dialog(m_msg_dlg_parent, msg_text, "", wxICON_WARNING | wxYES | wxNO); + DynamicPrintConfig new_conf = *config; + is_msg_dlg_already_exist = true; + auto answer = dialog.ShowModal(); + if (answer == wxID_YES) + new_conf.set_key_value("wall_generator", new ConfigOptionEnum(PerimeterGeneratorType::Arachne)); + else + new_conf.set_key_value("fuzzy_skin_mode", new ConfigOptionEnum(FuzzySkinMode::Displacement)); + apply(config, &new_conf); + is_msg_dlg_already_exist = false; + } } void ConfigManipulation::apply_null_fff_config(DynamicPrintConfig *config, std::vector const &keys, std::map const &configs) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 994367d8da..a6532c6850 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2454,6 +2454,7 @@ optgroup->append_single_option_line("skirt_loops", "others_settings_skirt#loops" optgroup = page->new_optgroup(L("Fuzzy Skin"), L"fuzzy_skin"); optgroup->append_single_option_line("fuzzy_skin", "others_settings_special_mode#fuzzy-skin"); + optgroup->append_single_option_line("fuzzy_skin_mode"); optgroup->append_single_option_line("fuzzy_skin_noise_type", "others_settings_special_mode#fuzzy-skin-mode"); optgroup->append_single_option_line("fuzzy_skin_point_distance", "others_settings_special_mode#point-distance"); optgroup->append_single_option_line("fuzzy_skin_thickness", "others_settings_special_mode#skin-thickness");