You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

正交相机相对旋转移动速度异常问题求助

相机相对自身旋转方向移动的速度问题修复

需求

实现相机跟随自身旋转方向移动:按下W键时相机相对自身向上移动,按下S键时以相同速度反向移动。

问题

当前相机添加的速度不可靠,无法达到预期的跟随旋转方向移动的效果。

异常函数代码

问题出在CameraAddRelativeVelocity函数中,输入该函数的velToAdd由下方输入处理函数生成,已验证输入处理逻辑正常:

void OrthographicCameraController::CameraAddRelativeVelocity(Timestep ts, glm::vec2 velocity)
{
    glm::vec2 rotatedVelocity(
        velocity.x * cos(glm::radians(m_CameraRotation)) + velocity.y * 
sin(glm::radians(m_CameraRotation)),
        velocity.x * sin(glm::radians(m_CameraRotation)) + velocity.y * cos(glm::radians(m_CameraRotation))
    );

    m_CameraVelocity += rotatedVelocity * (ts.GetMilliseconds() * 0.1f);

    // LOG_INFO("x, {0} y: {1}", velocity.x, velocity.y);
}

输入处理函数代码

bool xNegative = 0 > m_CameraVelocity.x;
bool xPositive = 0 < m_CameraVelocity.x;

bool yNegative = 0 > m_CameraVelocity.y;
bool yPositive = 0 < m_CameraVelocity.y;

glm::vec2 velToAdd = {0.0f, 0.0f};


if ((Input::IsKeyPressed(HZ_KEY_D) - Input::IsKeyPressed(HZ_KEY_A)) == 0) {
    
    if (m_CameraMovementRetardation * m_MaxCameraTranslationSpeed * ts > m_CameraVelocity.x && m_CameraMovementRetardation * m_MaxCameraTranslationSpeed * ts > -m_CameraVelocity.x) {
        m_CameraVelocity.x = 0;
    }
    else {
        m_CameraVelocity.x += m_CameraMovementRetardation * (xNegative - xPositive) * m_MaxCameraTranslationSpeed * ts;
    }

} else {
    velToAdd.x = (Input::IsKeyPressed(HZ_KEY_D) - Input::IsKeyPressed(HZ_KEY_A)) * m_CameraMovementAcceleration * m_MaxCameraTranslationSpeed * ts;
}


if ((Input::IsKeyPressed(HZ_KEY_W) - Input::IsKeyPressed(HZ_KEY_S)) == 0) {

    if (m_CameraMovementRetardation * m_MaxCameraTranslationSpeed * ts > m_CameraVelocity.y && m_CameraMovementRetardation * m_MaxCameraTranslationSpeed * ts > -m_CameraVelocity.y) {
        m_CameraVelocity.y = 0;
    }
    else {
        m_CameraVelocity.y += m_CameraMovementRetardation * (yNegative - yPositive) * m_MaxCameraTranslationSpeed * ts;
    }

}
else {
    velToAdd.y = (Input::IsKeyPressed(HZ_KEY_W) - Input::IsKeyPressed(HZ_KEY_S)) * m_CameraMovementAcceleration * m_MaxCameraTranslationSpeed * ts;
}


// Camera rotation

if (m_Rotation)
{
    if (Input::IsKeyPressed(HZ_KEY_E))
        m_CameraRotation += m_MaxCameraRotationSpeed * ts;
    if (Input::IsKeyPressed(HZ_KEY_Q))
        m_CameraRotation -= m_MaxCameraRotationSpeed * ts;

    if (m_CameraRotation > 180.0f)
        m_CameraRotation -= 360.0f;
    else if (m_CameraRotation <= -180.0f)
        m_CameraRotation += 360.0f;

    m_Camera.SetRotation(m_CameraRotation);
}

m_WorldSpaceMovement ? CameraAddWorldSpaceVelocity(ts, velToAdd) : CameraAddRelativeVelocity(ts, velToAdd);

m_CameraVelocity = glm::clamp(m_CameraVelocity, -m_MaxCameraTranslationSpeed, m_MaxCameraTranslationSpeed);

m_CameraPosition += m_CameraVelocity;
m_Camera.SetPosition(m_CameraPosition);

m_MaxCameraTranslationSpeed = m_ZoomLevel;

问题分析

  1. 旋转矩阵计算错误:原代码中的旋转向量转换公式不符合2D空间下相对方向转世界方向的逻辑,导致相机移动方向和自身旋转角度不匹配。
  2. 重复的时间步缩放:输入处理函数生成的velToAdd已经包含了时间步(ts)的计算,但CameraAddRelativeVelocity中再次乘以ts.GetMilliseconds() * 0.1f,导致速度被错误放大/缩小,表现为速度不稳定、过快或过慢。

修复后的函数代码

void OrthographicCameraController::CameraAddRelativeVelocity(Timestep ts, glm::vec2 velocity)
{
    float rotationRad = glm::radians(m_CameraRotation);
    float cosRot = cos(rotationRad);
    float sinRot = sin(rotationRad);

    // 正确的2D旋转矩阵:将相机相对方向转换为世界空间方向
    glm::vec2 rotatedVelocity(
        velocity.x * cosRot - velocity.y * sinRot,
        velocity.x * sinRot + velocity.y * cosRot
    );

    // 输入的velToAdd已包含时间步计算,无需再次缩放
    m_CameraVelocity += rotatedVelocity;

    // LOG_INFO("x, {0} y: {1}", velocity.x, velocity.y);
}

修复说明

  • 修正旋转矩阵的符号:相对相机的向上方向(W键对应的y正方向)在转换到世界空间时,需要减去velocity.y * sinRot,否则移动方向会与相机朝向相反。
  • 移除重复的时间步乘法:输入处理中的velToAdd已经通过* ts完成了时间积分,避免速度被重复缩放导致的不稳定问题。

内容的提问来源于stack exchange,提问作者a coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 20:57:32