From ad819850f972fe3e7f2dc3c3ffdcca918953b2da Mon Sep 17 00:00:00 2001 From: PavelMikus Date: Wed, 2 Mar 2022 11:58:31 +0100 Subject: [PATCH] tweaked parameters, fixed minor bugs --- src/libslic3r/GCode/SeamPlacerNG.cpp | 48 ++++++++++++---------------- src/libslic3r/GCode/SeamPlacerNG.hpp | 14 ++++---- 2 files changed, 28 insertions(+), 34 deletions(-) diff --git a/src/libslic3r/GCode/SeamPlacerNG.cpp b/src/libslic3r/GCode/SeamPlacerNG.cpp index 086cb0fdcc..bb31fcd62e 100644 --- a/src/libslic3r/GCode/SeamPlacerNG.cpp +++ b/src/libslic3r/GCode/SeamPlacerNG.cpp @@ -156,7 +156,7 @@ std::vector raycast_visibility(const AABBTreeIndirect::Tree<3, float> & // Prepare random samples per ray // std::random_device rnd_device; // use fixed seed, we can backtrack potential issues easier - std::mt19937 mersenne_engine { 12345 }; + std::mt19937 mersenne_engine { 131 }; std::uniform_real_distribution dist { 0, 1 }; auto gen = [&dist, &mersenne_engine]() { @@ -174,15 +174,19 @@ std::vector raycast_visibility(const AABBTreeIndirect::Tree<3, float> & BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: raycast visibility for " << ray_count << " rays: start"; - // raycast visibility + std::vector hit_points = tbb::parallel_reduce(tbb::blocked_range(0, ray_count), std::vector { }, [&](tbb::blocked_range r, std::vector init) { for (size_t index = r.begin(); index < r.end(); ++index) { + //generate global ray direction Vec3f global_ray_dir = sample_sphere_uniform(global_dir_random_samples[index]); + //place the ray origin on the bounding sphere Vec3f ray_origin = (vision_sphere_center - global_ray_dir * vision_sphere_raidus); + // compute local ray direction as cosine hemisphere sample - the rays dont aim directly to the middle Vec3f local_dir = sample_power_cosine_hemisphere(local_dir_random_samples[index], SeamPlacer::cosine_hemisphere_sampling_power); + // apply the local direction via Frame struct - the local_dir is with respect to +Z being forward Frame f; f.set_from_z(global_ray_dir); Vec3f final_ray_dir = (f.to_world(local_dir)); @@ -282,6 +286,7 @@ std::vector calculate_polygon_angles_at_vertices(const Polygon &polygon, return result; } +// structure to store global information about the model - occlusion hits, enforcers, blockers struct GlobalModelInfo { std::vector geometry_raycast_hits; KDTreeIndirect<3, float, HitInfoCoordinateFunctor> raycast_hits_tree; @@ -311,7 +316,7 @@ struct GlobalModelInfo { if (closest_point_index == raycast_hits_tree.npos || (position - geometry_raycast_hits[closest_point_index].position).norm() - > SeamPlacer::seam_align_tolerable_dist) { + > SeamPlacer::considered_area_radius) { return 0; } auto nearby_points = find_nearby_points(raycast_hits_tree, position, SeamPlacer::considered_area_radius); @@ -354,7 +359,7 @@ struct GlobalModelInfo { for (size_t i = 0; i < divided_mesh.vertices.size(); ++i) { float visibility = calculate_point_visibility(divided_mesh.vertices[i]); float normalized = visibility - / (SeamPlacer::expected_hits_per_area * PI * SeamPlacer::considered_area_radius); + / (SeamPlacer::expected_hits_per_area * SeamPlacer::considered_area_radius); Vec3f color = vis_to_rgb(normalized); fprintf(fp, "v %f %f %f %f %f %f\n", divided_mesh.vertices[i](0), divided_mesh.vertices[i](1), divided_mesh.vertices[i](2), @@ -576,9 +581,9 @@ void gather_global_model_info(GlobalModelInfo &result, const PrintObject *po) { struct DefaultSeamComparator { float compute_angle_penalty(float ccw_angle) const { if (ccw_angle >= 0) { - return PI - ccw_angle; + return PI * PI - ccw_angle * ccw_angle; } else { - return (PI - ccw_angle) * 1.1f; + return (PI * PI - ccw_angle * ccw_angle) * 0.8f; } } @@ -593,12 +598,12 @@ struct DefaultSeamComparator { } //avoid overhangs - if (a.overhang > 0.2f && b.overhang < a.overhang) { + if (a.overhang > 0.3f && b.overhang < a.overhang) { return false; } - return (a.visibility + 0.01) * compute_angle_penalty(a.local_ccw_angle) < - (b.visibility + 0.01) * compute_angle_penalty(b.local_ccw_angle); + return (a.visibility + SeamPlacer::expected_hits_per_area) * compute_angle_penalty(a.local_ccw_angle) < + (b.visibility + SeamPlacer::expected_hits_per_area) * compute_angle_penalty(b.local_ccw_angle); } bool is_first_not_much_worse(const SeamCandidate &a, const SeamCandidate &b) const { @@ -611,12 +616,12 @@ struct DefaultSeamComparator { } //avoid overhangs - if (a.overhang > 0.2f && b.overhang < a.overhang) { + if (a.overhang > 0.3f && b.overhang < a.overhang) { return false; } - return (a.visibility + 0.01) * compute_angle_penalty(a.local_ccw_angle) * 0.8f <= - (b.visibility + 0.01) * compute_angle_penalty(b.local_ccw_angle); + return (a.visibility + SeamPlacer::expected_hits_per_area) * compute_angle_penalty(a.local_ccw_angle) * 0.8f <= + (b.visibility + SeamPlacer::expected_hits_per_area) * compute_angle_penalty(b.local_ccw_angle); } } ; @@ -691,9 +696,6 @@ tbb::parallel_for(tbb::blocked_range(0, m_perimeter_points_per_object[po if (layer_idx > 0) { //calculate overhang perimeter_point.overhang = calculate_layer_overhang(layer_idx-1); } - if (layer_idx < m_perimeter_points_per_object[po].size() - 1) { //calculate higher_layer_overhang - perimeter_point.higher_layer_overhang = calculate_layer_overhang(layer_idx+1); - } } } }); @@ -776,19 +778,11 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const Comparator &comp } } - //sort them by visiblity, before aligning + //sort them and then align starting with the best candidates std::sort(seams.begin(), seams.end(), [&](const std::pair &left, const std::pair &right) { - return m_perimeter_points_per_object[po][left.first][left.second].visibility - * (1.2 * PI - - std::abs( - m_perimeter_points_per_object[po][left.first][left.second].local_ccw_angle - - 0.2 * PI)) - < m_perimeter_points_per_object[po][right.first][right.second].visibility - * (1.2 * PI - - std::abs( - m_perimeter_points_per_object[po][right.first][right.second].local_ccw_angle - - 0.2 * PI)); + return comparator.is_first_better(m_perimeter_points_per_object[po][left.first][left.second], + m_perimeter_points_per_object[po][right.first][right.second]); } ); @@ -850,7 +844,7 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const Comparator &comp m_perimeter_points_per_object[po][seam_string[index].first][seam_string[index].second].position; } - std::vector coefficients = polyfit(points, 4); + std::vector coefficients = polyfit(points, 3); for (const auto &pair : seam_string) { float current_height = m_perimeter_points_per_object[po][pair.first][pair.second].position.z(); Vec3f seam_pos = get_fitted_point(coefficients, current_height); diff --git a/src/libslic3r/GCode/SeamPlacerNG.hpp b/src/libslic3r/GCode/SeamPlacerNG.hpp index bcd178aed7..ec27938b1b 100644 --- a/src/libslic3r/GCode/SeamPlacerNG.hpp +++ b/src/libslic3r/GCode/SeamPlacerNG.hpp @@ -97,21 +97,21 @@ public: using SeamCandidatesTree = KDTreeIndirect<3, float, SeamPlacerImpl::SeamCandidateCoordinateFunctor>; // Rough estimates of hits of the mesh during raycasting per surface circle defined by considered_area_radius - static constexpr float expected_hits_per_area = 600.0f; + static constexpr float expected_hits_per_area = 400.0f; // area considered when computing number of rays and then gathering visiblity info from the hits - static constexpr float considered_area_radius = 3.0f; + static constexpr float considered_area_radius = 4.0f; // quadric error limit of quadric decimation function used on the mesh before raycasting - static constexpr float raycasting_decimation_target_error = 0.3f; + static constexpr float raycasting_decimation_target_error = 0.1f; // cosine sampling power represents how prefered are forward directions when raycasting from given spot // in this case, forward direction means towards the center of the mesh static constexpr float cosine_hemisphere_sampling_power = 4.0f; // arm length used during angles computation - static constexpr float polygon_local_angles_arm_distance = 0.6f; + static constexpr float polygon_local_angles_arm_distance = 1.0f; // If enforcer or blocker is closer to the seam candidate than this limit, the seam candidate is set to Blocer or Enforcer - static constexpr float enforcer_blocker_sqr_distance_tolerance = 0.2f; + static constexpr float enforcer_blocker_sqr_distance_tolerance = 0.1f; // When searching for seam clusters for alignment: // seam_align_tolerable_dist - if seam is closer to the previous seam position projected to the current layer than this value, @@ -119,9 +119,9 @@ public: static constexpr float seam_align_tolerable_dist = 1.0f; // if the seam of the current layer is too far away, and the closest seam candidate is not very good, layer is skipped. // this param limits the number of allowed skips - static constexpr size_t seam_align_tolerable_skips = 6; + static constexpr size_t seam_align_tolerable_skips = 4; // minimum number of seams needed in cluster to make alignemnt happen - static constexpr size_t seam_align_minimum_string_seams = 5; + static constexpr size_t seam_align_minimum_string_seams = 4; //The following data structures hold all perimeter points for all PrintObject. The structure is as follows: // Map of PrintObjects (PO) -> vector of layers of PO -> vector of perimeter points of the given layer