From 5cc9b14d73f70a8332c5d031b1d81ad689497617 Mon Sep 17 00:00:00 2001 From: atdunbg Date: Sat, 3 Oct 2026 01:49:42 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=97=8B=E8=BD=AC=20snap=20=E5=8D=95?= =?UTF-8?q?=E4=BD=8D=E4=BF=AE=E6=AD=A3=EF=BC=88=E5=BA=A6=E9=9D=9E=E5=BC=A7?= =?UTF-8?q?=E5=BA=A6=EF=BC=89+=20=E8=BD=B4=E5=8F=AF=E8=A7=81=E5=BA=A6?= =?UTF-8?q?=E9=98=88=E5=80=BC=E5=AF=B9=E9=BD=90=20UE=20=E6=AD=A3=E5=AF=B9?= =?UTF-8?q?=E8=BD=B4=E9=9A=90=E8=97=8F=E8=AF=AD=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 两个实锤问题(源码数学 + 数值仿真定位): 1. 旋转 snap 传了 glm::radians(15°)≈0.26,而库按"度"解释 (docs/documentation.md:snap angles are in degrees,库内自行 DEG2RAD)→ 实际步进 0.26° 形同虚设。改传 15.0 2. 正对视角两症状同根因(view-aligned axis degeneracy): - 轴⊥视线:悬停检测的射线-垂直平面求交 denom=0 → len=-1 → 无法 hover(动视角即恢复) - 轴∥视线:屏幕投影无一阶位移 → 怎么拖都不动 默认 mPlaneLimit=0.02 太小,"有高度差"视角下投影 sinθ≈0.17~0.34 刚好高于阈值 = 看得见但几何上不可操作。提至 0.35:夹角 <20° 的 轴自动隐藏(UE 同语义),>20° 正常可拖 --- App/editor/ViewportPanel.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/App/editor/ViewportPanel.cpp b/App/editor/ViewportPanel.cpp index 734ffd9..1650780 100644 --- a/App/editor/ViewportPanel.cpp +++ b/App/editor/ViewportPanel.cpp @@ -146,6 +146,13 @@ std::optional ViewportPanel::Draw(const EditorContext &ctx, const ImVec2 mn = ImGui::GetItemRectMin(); ImGuizmo::SetRect(mn.x, mn.y, size.x, size.y); + // 轴可见度阈值(默认 0.02 太小):正对视角下轴投影长度 + // sinθ 在阈值上方 → "看得见但几何上不可操作"——⊥视线 + // 的轴悬停检测失效(射线∥垂直平面,denom=0)、∥视线 + // 的轴拖拽无一阶位移(怎么拖都不动)。UE 语义 = 正对 + // 轴直接隐藏:0.35 ⇒ 夹角 <20° 的轴消失,>20° 可拖 + ImGuizmo::SetPlaneLimit(0.35f); + glm::mat4 m = tr->World(); // 操作空间:local(模型轴,旋转/缩放随物体朝向直观)/ // world(T 键切换)。无父层级时两种模式 world 矩阵同源, @@ -153,17 +160,19 @@ std::optional ViewportPanel::Draw(const EditorContext &ctx, const ImGuizmo::MODE mode = gizmo.localSpace ? ImGuizmo::LOCAL : ImGuizmo::WORLD; - // Ctrl 按住 → 吸附(UE Grid Snap 语义)。ImGuizmo 约定: - // 平移 snap = 世界单位(逐轴)、旋转 = 弧度、缩放 = 步进 + // Ctrl 按住 → 吸附(UE Grid Snap 语义)。库的约定 + //(docs/documentation.md):平移 = 世界单位 float[3] + // 逐轴;旋转 = snap[0] 按度(库内自行 DEG2RAD,传弧度 + // 会被解释成极小步进);缩放 = 只取 snap[0] float snap[3] = {0.0f, 0.0f, 0.0f}; const bool snapping = ImGui::GetIO().KeyCtrl; if (snapping) { if (gizmo.op == ImGuizmo::TRANSLATE) { snap[0] = snap[1] = snap[2] = kSnapTranslate; } else if (gizmo.op == ImGuizmo::ROTATE) { - snap[0] = glm::radians(kSnapRotateDeg); + snap[0] = kSnapRotateDeg; // 度,非弧度 } else if (gizmo.op == ImGuizmo::SCALE) { - snap[0] = snap[1] = snap[2] = kSnapScale; + snap[0] = kSnapScale; } }