From 8f3ed9bc7bab0304c822493cc062155e3e8d1995 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Tue, 29 Jul 2025 21:11:35 +0800 Subject: [PATCH] Introduce a new seam alignment option: Aligned back (#10255) * Introduce a new seam alignment option: spAlignedBack. --- src/libslic3r/GCode/SeamPlacer.cpp | 27 +++++++++++++++++---------- src/libslic3r/PrintConfig.cpp | 5 ++++- src/libslic3r/PrintConfig.hpp | 2 +- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 6927cb554b..b2b49ec6e7 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -128,7 +128,8 @@ Vec3f sample_power_cosine_hemisphere(const Vec2f &samples, float power) { std::vector raycast_visibility(const AABBTreeIndirect::Tree<3, float> &raycasting_tree, const indexed_triangle_set &triangles, const TriangleSetSamples &samples, - size_t negative_volumes_start_index) { + size_t negative_volumes_start_index, + SeamPosition seam_position = spAligned) { BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: raycast visibility of " << samples.positions.size() << " samples over " << triangles.indices.size() << " triangles: end"; @@ -151,7 +152,7 @@ std::vector raycast_visibility(const AABBTreeIndirect::Tree<3, float> &ra std::vector result(samples.positions.size()); tbb::parallel_for(tbb::blocked_range(0, result.size()), [&triangles, &precomputed_sample_directions, model_contains_negative_parts, negative_volumes_start_index, - &raycasting_tree, &result, &samples](tbb::blocked_range r) { + &raycasting_tree, &result, &samples, seam_position](tbb::blocked_range r) { // Maintaining hits memory outside of the loop, so it does not have to be reallocated for each query. std::vector hits; for (size_t s_idx = r.begin(); s_idx < r.end(); ++s_idx) { @@ -161,6 +162,11 @@ std::vector raycast_visibility(const AABBTreeIndirect::Tree<3, float> &ra const Vec3f ¢er = samples.positions[s_idx]; const Vec3f &normal = samples.normals[s_idx]; + if (seam_position == spAlignedBack) { + const float front_adjustment = std::clamp((normal.dot(Vec3f(0.0f, -1.0f, 0.0f)) + 1.2f) * 0.5f, 0.0f, 1.0f); + result[s_idx] += front_adjustment; + } + // apply the local direction via Frame struct - the local_dir is with respect to +Z being forward Frame f; f.set_from_z(normal); @@ -617,7 +623,8 @@ std::pair find_previous_and_next_perimeter_point(const std::vect // Computes all global model info - transforms object, performs raycasting void compute_global_occlusion(GlobalModelInfo &result, const PrintObject *po, - std::function throw_if_canceled) { + std::function throw_if_canceled, + SeamPosition seam_position = spAligned) { BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: gather occlusion meshes: start"; auto obj_transform = po->trafo_centered(); @@ -692,7 +699,7 @@ void compute_global_occlusion(GlobalModelInfo &result, const PrintObject *po, BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: build AABB tree: end"; result.mesh_samples_visibility = raycast_visibility(raycasting_tree, triangle_set, result.mesh_samples, - negative_volumes_start_index); + negative_volumes_start_index, seam_position); throw_if_canceled(); #ifdef DEBUG_FILES result.debug_export(triangle_set); @@ -741,7 +748,7 @@ struct SeamComparator { // should return if a is better seamCandidate than b bool is_first_better(const SeamCandidate &a, const SeamCandidate &b, const Vec2f &preffered_location = Vec2f { 0.0f, 0.0f }) const { - if (setup == SeamPosition::spAligned && a.central_enforcer != b.central_enforcer) { + if ((setup == SeamPosition::spAligned || setup == SeamPosition::spAlignedBack) && a.central_enforcer != b.central_enforcer) { return a.central_enforcer; } @@ -790,7 +797,7 @@ struct SeamComparator { // Also used by the random seam generator. bool is_first_not_much_worse(const SeamCandidate &a, const SeamCandidate &b) const { // Blockers/Enforcers discrimination, top priority - if (setup == SeamPosition::spAligned && a.central_enforcer != b.central_enforcer) { + if ((setup == SeamPosition::spAligned || setup == SeamPosition::spAlignedBack) && a.central_enforcer != b.central_enforcer) { // Prefer centers of enforcers. return a.central_enforcer; } @@ -1426,8 +1433,8 @@ void SeamPlacer::init(const Print &print, std::function throw_if_can GlobalModelInfo global_model_info { }; gather_enforcers_blockers(global_model_info, po); throw_if_canceled_func(); - if (configured_seam_preference == spAligned || configured_seam_preference == spNearest) { - compute_global_occlusion(global_model_info, po, throw_if_canceled_func); + if (configured_seam_preference == spAligned || configured_seam_preference == spNearest || configured_seam_preference == spAlignedBack) { + compute_global_occlusion(global_model_info, po, throw_if_canceled_func, configured_seam_preference); } throw_if_canceled_func(); BOOST_LOG_TRIVIAL(debug) @@ -1436,7 +1443,7 @@ void SeamPlacer::init(const Print &print, std::function throw_if_can BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: gather_seam_candidates: end"; throw_if_canceled_func(); - if (configured_seam_preference == spAligned || configured_seam_preference == spNearest) { + if (configured_seam_preference == spAligned || configured_seam_preference == spNearest || configured_seam_preference == spAlignedBack) { BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: calculate_candidates_visibility : start"; calculate_candidates_visibility(po, global_model_info); @@ -1472,7 +1479,7 @@ void SeamPlacer::init(const Print &print, std::function throw_if_can << "SeamPlacer: pick_seam_point : end"; } throw_if_canceled_func(); - if (configured_seam_preference == spAligned || configured_seam_preference == spRear) { + if (configured_seam_preference == spAligned || configured_seam_preference == spRear || configured_seam_preference == spAlignedBack) { BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: align_seam_points : start"; align_seam_points(po, comparator); diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 24e29459ed..a4b640d518 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -270,8 +270,9 @@ CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SupportType) static t_config_enum_values s_keys_map_SeamPosition { { "nearest", spNearest }, { "aligned", spAligned }, + { "aligned_back", spAlignedBack }, { "back", spRear }, - { "random", spRandom }, + { "random", spRandom } }; CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(SeamPosition) @@ -4365,10 +4366,12 @@ void PrintConfigDef::init_fff_params() def->enum_keys_map = &ConfigOptionEnum::get_enum_values(); def->enum_values.push_back("nearest"); def->enum_values.push_back("aligned"); + def->enum_values.push_back("aligned_back"); def->enum_values.push_back("back"); def->enum_values.push_back("random"); def->enum_labels.push_back(L("Nearest")); def->enum_labels.push_back(L("Aligned")); + def->enum_labels.push_back(L("Aligned back")); def->enum_labels.push_back(L("Back")); def->enum_labels.push_back(L("Random")); def->mode = comSimple; diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index c2f38ae0b0..1093d4071a 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -176,7 +176,7 @@ inline bool is_auto(SupportType stype) }; enum SeamPosition { - spNearest, spAligned, spRear, spRandom + spNearest, spAligned, spAlignedBack, spRear, spRandom }; // Orca