正交相机相对旋转移动速度异常问题求助
相机相对自身旋转方向移动的速度问题修复
需求
实现相机跟随自身旋转方向移动:按下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;
问题分析
- 旋转矩阵计算错误:原代码中的旋转向量转换公式不符合2D空间下相对方向转世界方向的逻辑,导致相机移动方向和自身旋转角度不匹配。
- 重复的时间步缩放:输入处理函数生成的
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
相关产品推荐
相关产品推荐

