feat(editor): Gizmo 退化轴自动隐藏(调用层 SetAxisMask,UE 语义)
正对视角 + 物体竖直偏移时,单轴拖拽灵敏度 sinθ(轴与相机连线夹角)→0: 拖拽投影系数趋 0("数值不变"),激活平面与鼠标射线共面(IntersectRayPlane denom→0 返回 -1 被当交点距离)。按灵敏度 <0.25(θ<14.5°)将病态轴 SetAxisMask 隐藏(库公开 API,按轴关绘制+激活,保留含该轴的平面手柄 与中心块兜底),相机移动后自动恢复——可激活性决定可见性,零库改动。
This commit is contained in:
@@ -40,6 +40,12 @@ namespace
|
|||||||
constexpr float kSnapRotateDeg = 15.0f; // 度
|
constexpr float kSnapRotateDeg = 15.0f; // 度
|
||||||
constexpr float kSnapScale = 0.1f; // 缩放步进
|
constexpr float kSnapScale = 0.1f; // 缩放步进
|
||||||
|
|
||||||
|
// 单轴拖拽灵敏度下限:sinθ(轴与"相机→物体"连线夹角)。低于该值
|
||||||
|
// 时拖拽投影系数 <0.25 且激活平面与鼠标射线近共面——视觉上
|
||||||
|
// "看得见、抓了没反应"。≈14.5°,略宽于库默认可见角(≈11.5°),
|
||||||
|
// 只藏真正病态的轴,不动可用轴
|
||||||
|
constexpr float kAxisMinSin = 0.25f;
|
||||||
|
|
||||||
// Vulkan proj → ImGuizmo 期望的 OpenGL 形式(Y-up、Z∈[-1,1]):
|
// Vulkan proj → ImGuizmo 期望的 OpenGL 形式(Y-up、Z∈[-1,1]):
|
||||||
// Y 行翻回(抵消 Vulkan clip Y 向下翻转);z 行 = 2*z - w 即
|
// Y 行翻回(抵消 Vulkan clip Y 向下翻转);z 行 = 2*z - w 即
|
||||||
// 深度 [0,1] → [-1,1]。glm 列主序 m[col][row],逐列改 row1/row2
|
// 深度 [0,1] → [-1,1]。glm 列主序 m[col][row],逐列改 row1/row2
|
||||||
@@ -146,9 +152,7 @@ std::optional<entt::entity> ViewportPanel::Draw(const EditorContext &ctx,
|
|||||||
const ImVec2 mn = ImGui::GetItemRectMin();
|
const ImVec2 mn = ImGui::GetItemRectMin();
|
||||||
ImGuizmo::SetRect(mn.x, mn.y, size.x, size.y);
|
ImGuizmo::SetRect(mn.x, mn.y, size.x, size.y);
|
||||||
|
|
||||||
// 不调 SetPlaneLimit/SetAxisLimit——全默认参数,与
|
// 不调 SetPlaneLimit/SetAxisLimit——可见度保持库默认
|
||||||
// Horizon 同款(官方库出货行为:轴仅在几乎正对视线
|
|
||||||
// 时隐藏,任何自行抬高阈值都会过早藏轴)
|
|
||||||
|
|
||||||
glm::mat4 m = tr->World();
|
glm::mat4 m = tr->World();
|
||||||
// 操作空间:local(模型轴,旋转/缩放随物体朝向直观)/
|
// 操作空间:local(模型轴,旋转/缩放随物体朝向直观)/
|
||||||
@@ -157,6 +161,33 @@ std::optional<entt::entity> ViewportPanel::Draw(const EditorContext &ctx,
|
|||||||
const ImGuizmo::MODE mode =
|
const ImGuizmo::MODE mode =
|
||||||
gizmo.localSpace ? ImGuizmo::LOCAL : ImGuizmo::WORLD;
|
gizmo.localSpace ? ImGuizmo::LOCAL : ImGuizmo::WORLD;
|
||||||
|
|
||||||
|
// 退化轴隐藏(UE 语义:可激活性决定可见性)。库的单轴
|
||||||
|
// 激活平面包含"轴 + 相机连线",鼠标射线∥连线时求交
|
||||||
|
// denom→0 返回 -1 被当交点距离(L2347-2349),拖拽
|
||||||
|
// delta 在轴上的投影系数 = sinθ 也同时趋 0——表现为
|
||||||
|
// "杆看得见、抓了没反应/数值不变"。按灵敏度把病态轴
|
||||||
|
// SetAxisMask 隐藏(库内按轴关绘制+激活,单轴 mask
|
||||||
|
// 时保留含该轴的平面手柄兜底);相机一移动自动恢复
|
||||||
|
const glm::vec3 camPos(glm::inverse(view)[3]);
|
||||||
|
glm::vec3 camToObj = glm::vec3(m[3]) - camPos;
|
||||||
|
const float camDist = glm::length(camToObj);
|
||||||
|
const glm::mat3 rotM(m);
|
||||||
|
bool maskAxis[3] = {false, false, false};
|
||||||
|
if (camDist > 1e-4f) {
|
||||||
|
camToObj /= camDist;
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
const glm::vec3 axis = gizmo.localSpace
|
||||||
|
? glm::normalize(rotM[i])
|
||||||
|
: glm::vec3(float(i == 0), float(i == 1),
|
||||||
|
float(i == 2));
|
||||||
|
maskAxis[i] =
|
||||||
|
glm::length(glm::cross(camToObj, axis))
|
||||||
|
< kAxisMinSin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGuizmo::SetAxisMask(maskAxis[0], maskAxis[1],
|
||||||
|
maskAxis[2]);
|
||||||
|
|
||||||
// Ctrl 按住 → 吸附(UE Grid Snap 语义)。库的约定
|
// Ctrl 按住 → 吸附(UE Grid Snap 语义)。库的约定
|
||||||
//(docs/documentation.md):平移 = 世界单位 float[3]
|
//(docs/documentation.md):平移 = 世界单位 float[3]
|
||||||
// 逐轴;旋转 = snap[0] 按度(库内自行 DEG2RAD,传弧度
|
// 逐轴;旋转 = snap[0] 按度(库内自行 DEG2RAD,传弧度
|
||||||
|
|||||||
Reference in New Issue
Block a user