fix(editor): rotation drag accumulates without wrap (UE session semantics)

Dragging rotation hit a wall at the wrap point: each frame re-read
euler from the quat and wrapped to [0,360), so dragging past 360
snapped the display back to 0 (and backwards dragging wrapped up to
360) -- values "jumped around" instead of accumulating.

Port UE TransformDetails session semantics: the rotation row shows a
local mirror value while the user edits it (accumulating freely in
both directions, never wrapping), and re-syncs from the quat only on
foreign changes (gizmo drag, physics writeback, entity switch).
Detection is exact component-wise quat equality: the mirror quat comes
from the same QuatFromEuler used by SetRotation, so an untouched pair
compares bit-equal, while any foreign writeback -- including sub-0.05
degree gizmo steps that a dot-product threshold would miss -- differs
in at least one float. Edit frames skip the check (mirror leads the
quat by one drag delta), gated on the previous frame's item-active
state.
This commit is contained in:
2026-10-04 02:00:42 +08:00
parent 4498bc7535
commit 90097a756e
2 changed files with 65 additions and 9 deletions
+9 -2
View File
@@ -98,13 +98,20 @@ namespace Engine::ECS {
TransformComponent& SetPosition(const glm::vec3& p) { if (m_Position != p) { m_Position = p; m_Dirty = true; } return *this; }
// 欧拉角(度)入口:UI/游戏逻辑用。转 quat 存(q = qy·qx·qz,
// 与原 Ry·Rx·Rz 合成严格同构;不能用 glm::quat(euler) ctor——
// 那是 ZYX 航向序,语义不同)
// 那是 ZYX 航向序,语义不同)。输入域无限制:三角函数周期性
// 自动归一(720 ≡ -45 ≡ 315),编辑器拖动累计值直接喂
TransformComponent& SetRotation(const glm::vec3& r)
{
return SetRotationQuat(QuatFromEuler(r));
}
// 欧拉(度)→ quat 的唯一转换点(qy·qx·qz)。static 供编辑器
// mirror 的旋转等价检测复用(同一公式构造 → dot 判定严格)
static glm::quat QuatFromEuler(const glm::vec3& r)
{
const glm::quat qx = glm::angleAxis(glm::radians(r.x), glm::vec3(1, 0, 0));
const glm::quat qy = glm::angleAxis(glm::radians(r.y), glm::vec3(0, 1, 0));
const glm::quat qz = glm::angleAxis(glm::radians(r.z), glm::vec3(0, 0, 1));
return SetRotationQuat(qy * qx * qz);
return qy * qx * qz;
}
// 四元数直写(UE FTransform 语义):Gizmo 拖拽/物理写回用,
// 不经欧拉往返 → 零漂移、无万向锁