qt openGL入门笔记】FPS相机和轨道相机

前言

本篇是在上一篇【qt openGL入门笔记】FPS相机-CSDN博客的基础上增加轨道相交功能。两种相机在概念上是不一样的,FPS相机是以第一人称行走时"眼睛"的角度看物体的变化;而轨道相交是绕着目标点转,类似于绕着轨道转动的卫星(视角是一直看着目标点)。

效果图

功能详解

整体改动较小,主要改动在渲染和键值响应上。

键值改动

GLWidget类中,增加了多Key_Space键值捕获,用于切换相机模式。

鼠标点击事件传递进Camera类中,增加了右键和中键的平移,左键的绕目标旋转效果

复制代码
if (m_mode == Mode::Orbit) {
    if (m_rotating) {                      // 左键:绕目标旋转
        m_yaw   += dx * m_lookSensitivity;
        m_pitch  = qBound(-89, m_pitch + dyUp * ..., 89);
    } else if (m_panning) {                // 右键:平移目标点(平移视角)
        const float wpp = worldPerPixel();
        m_target -= m_right * (dx   * wpp);
        m_target -= m_up    * (dyUp * wpp);
    }
} else {
    if (m_rotating) { /* FPS:只有左键转视角 */ }
}


//屏幕上拖动 1 个像素,等于世界里平移了多少单位
float Camera::worldPerPixel() const
{
    const float h = m_viewportH > 0 ? float(m_viewportH) : 800.0f;
    return 2.0f * m_orbitDistance * qTan(qDegreesToRadians(m_fov) * 0.5f) / h;
}

新增了滚轮的缩放效果

复制代码
if (m_mode == Mode::Orbit) {//滚轮缩放
        m_orbitDistance *= qPow(0.85f, steps);
        m_orbitDistance  = qBound(m_minDistance, m_orbitDistance, m_maxDistance);
    } else {
        m_moveSpeed *= qPow(1.15f, steps);
        m_moveSpeed  = qBound(1.0f, m_moveSpeed, 300.0f);
    }

重置功能的变化

复制代码
// ============================================================
// F 复位:只复位"当前模式",不切换模式
// ============================================================
void Camera::reset()
{
    m_keysHeld.clear();
    m_rotating = m_panning = false;

    if (m_mode == Mode::FPS) {
        applySpawnPose(m_mode);          // FPS:瞬间重置
        updateCameraVectors();
        return;
    }

    // Orbit:记录起点,0.6s 缓动飞回默认机位
    const QVector3D& eye    = m_spawnEye[int(m_mode)];
    const QVector3D& center = m_spawnCenter[int(m_mode)];
    const QVector3D dir = (center - eye).normalized();
    m_flyToYaw     = qRadiansToDegrees(qAtan2(dir.z(), dir.x()));
    m_flyToPitch   = qRadiansToDegrees(qAsin(qBound(-1.0f, dir.y(), 1.0f)));
    m_flyToDist    = (center - eye).length();
    m_flyToTarget  = center;

    m_flyFromYaw    = m_yaw;
    m_flyFromPitch  = m_pitch;
    m_flyFromDist   = m_orbitDistance;
    m_flyFromTarget = m_target;

    m_flyT   = 0.0f;
    m_flying = true;
}

渲染改动

updateCameraVectors()增加重新计算了m_position,不是FPS相机的"跟随移动",而是"绕着目标转"

复制代码
if (m_mode == Mode::Orbit) {
    m_position = m_target - m_front * m_orbitDistance;
}

新增了模式切换函数

复制代码
// ============================================================
// 模式切换(保持视角连续)
// ============================================================
void Camera::setMode(Mode mode)
{
    if (mode == m_mode) return;

    m_flying = false;                       // 切模式打断飞行动画

    if (mode == Mode::Orbit) {
        m_target = m_position + m_front * m_orbitDistance;
    }

    m_mode     = mode;
    m_rotating = false;
    m_panning  = false;
    m_keysHeld.clear();
    updateCameraVectors();
}

需要注意的时,视图矩阵函数viewMatrix()和投影矩阵函数projectionMatrix()中的公式是没有变化的,但是公式里面的成员变量m_position, m_position + m_front, m_worldUp已经在键值变化时,一起变化了,所以VP也是一起变化的。

相关推荐
尘客-追梦1 小时前
qmake / jom / 影子构建:把编译管起来
开发语言·c++·qt
qeen872 小时前
【QT】 信号与槽初始
开发语言·笔记·qt·学习
Quz2 天前
QML PathView:吸附对齐与环形轮播
qt
时间的拾荒人2 天前
Qt 多线程详解:从 QThread 到实战
开发语言·qt·面试
时间的拾荒人2 天前
Qt 事件机制全解析:从事件处理到事件过滤器
开发语言·qt·面试
时间的拾荒人2 天前
Qt 窗口系统详解:从菜单栏到对话框的完整指南
开发语言·qt·面试
qq_401700412 天前
Qt 炫酷曲线,图表,2D/3D开源库
开发语言·qt
扶尔魔ocy2 天前
【qt openGL入门笔记】基础光照
qt·opengl
时间的拾荒人2 天前
Qt 文件操作详解:从基础类到读写实战
开发语言·qt·面试