From 6fd2de76e6b9274b4811d8f92cfc8c9acd00416c Mon Sep 17 00:00:00 2001 From: harrierpigeon Date: Wed, 5 Aug 2026 03:35:12 -0500 Subject: [PATCH] Fix: preserve upstream select-by-angle behavior when build plate is untilted (R7) select_facets_by_angle replaced upstream's limit.dot(down) threshold with cos(threshold), changing facet selection for non-uniformly-scaled/mirror objects on ALL printers. Restore the exact upstream computation when no build-plate tilt is active; keep the tilted-gravity form only under tilt. --- src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index 26afdbbe33..c0d791aa00 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -567,7 +567,12 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block) auto [tilt_x_deg, tilt_y_deg] = get_build_plate_tilt(); double tilt_x_rad = tilt_x_deg * M_PI / 180.0; double tilt_y_rad = tilt_y_deg * M_PI / 180.0; - Vec3d gravity_dir = Vec3d(-tan(tilt_y_rad), -tan(tilt_x_rad), -1.0).normalized(); + const bool has_tilt = (tilt_x_deg != 0. || tilt_y_deg != 0.); + // NB: use an if, not a ?:, so each branch converts to Vec3d independently + // (the two Eigen expression types don't unify in a ternary). + Vec3d gravity_dir = -Vec3d::UnitZ(); + if (has_tilt) + gravity_dir = Vec3d(-tan(tilt_y_rad), -tan(tilt_x_rad), -1.0).normalized(); int mesh_id = -1; for (const ModelVolume* mv : mo->volumes) { @@ -578,7 +583,16 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block) const Transform3d trafo_matrix = mi->get_matrix_no_offset() * mv->get_matrix_no_offset(); Vec3f down = (trafo_matrix.inverse() * gravity_dir).cast().normalized(); - float dot_limit = std::cos(threshold); + float dot_limit; + if (!has_tilt) { + // Exact upstream computation: threshold derived from a tilted limit + // vector transformed into mesh space, so non-uniform/mirror/shear + // transforms behave identically to upstream. + Vec3f limit = (trafo_matrix.inverse() * Vec3d(std::sin(threshold), 0, -std::cos(threshold))).cast().normalized(); + dot_limit = limit.dot(down); + } else { + dot_limit = std::cos(threshold); + } // Now calculate dot product of vert_direction and facets' normals. int idx = 0;