Qt OpenGL(06)坐标变换MVP后的效果

OpenGL中的观察坐标

OpenGL中的坐标变换过程如下所示:

在这里插入图片描述

计算机观察

观察三维世界空间的就是模拟了人通过照相机取景器看东西的过程,将物体置入观察空间,也就是让我们可以看到这个物体。

在这里插入图片描述在这里插入图片描述

照相机的初始方向是指向 Z 轴的负方向,在大多数应用程序中,我们在原点的附近建模对象, 因此默认方位的照相机无法生成包含场景中全部对象的图像。 这样,要么把照相机移走,使之远离我们希望成像的对象;要么把对象移到照相机的前面。这两个操作是等价的,因为它们都可以 看做是在对象标架下指定照相机标架。

详细查阅 OpenGL 经典照相机模型

Camera的欧拉角

在这里插入图片描述

透视变换

主要是视角,比例,近面,远面

在这里插入图片描述

正交投影

在这里插入图片描述

Camera 对象

通过键鼠控制的摄像头形成自由观察

Camera.hpp,这代码来自 Learn Modern OpenGL的网站,代码拷贝过来,简单修改就能在Qt中使用。

#ifndef CAMERA_H
#define CAMERA_H

#include <QtMath>
#include <QMatrix4x4>
#include <QVector3D>

// 定义 Camera 移动的几个可能选项。用作抽象,以远离特定于窗口系统的输入方法
enum Camera_Movement {
    FORWARD,
    BACKWARD,
    LEFT,
    RIGHT
};

// 默认 Camera 值
const float YAW         = -90.0f;
const float PITCH       =  0.0f;
const float SPEED       =  2.5f;
const float SENSITIVITY =  0.1f;
const float ZOOM        =  45.0f;


// 一个抽象的相机类,用于处理输入并计算相应的欧拉角、向量和矩阵,供OpenGL使用
class Camera
{
public:
    // Camera 属性
    QVector3D Position;
    QVector3D Front;
    QVector3D Up;
    QVector3D Right;
    QVector3D WorldUp;
    // euler Angles
    float Yaw;
    float Pitch;
    // camera options
    float MovementSpeed;
    float MouseSensitivity;
    float Zoom;

    // 带向量的构造函数
    Camera(QVector3D position = QVector3D(0.0f, 0.0f, 3.0f),
           QVector3D up = QVector3D(0.0f, 1.0f, 0.0f),
           float yaw = YAW, float pitch = PITCH)
        : Front(QVector3D(0.0f, 0.0f, -1.0f))
        , MovementSpeed(SPEED)
        , MouseSensitivity(SENSITIVITY)
        , Zoom(ZOOM)
    {
        Position = position;
        WorldUp = up;
        Yaw = yaw;
        Pitch = pitch;
        updateCameraVectors();
    }
    // 带标量的构造函数
    Camera(float posX, float posY, float posZ,
           float upX, float upY, float upZ, float yaw, float pitch)
        : Front(QVector3D(0.0f, 0.0f, -1.0f))
        , MovementSpeed(SPEED)
        , MouseSensitivity(SENSITIVITY)
        , Zoom(ZOOM)
    {
        Position = QVector3D(posX, posY, posZ);
        WorldUp = QVector3D(upX, upY, upZ);
        Yaw = yaw;
        Pitch = pitch;
        updateCameraVectors();
    }

    // 返回使用欧拉角和LookAt矩阵计算的视图矩阵
    QMatrix4x4 GetViewMatrix()
    {
        QMatrix4x4 mat;
        mat.lookAt(Position, Position + Front, Up);
        return mat;
    }

    // 处理从任何类似键盘的输入系统接收的输入。接受相机定义ENUM形式的输入参数(从窗口系统中抽象出来)
    void ProcessKeyboard(Camera_Movement direction, float deltaTime)
    {
        float velocity = MovementSpeed * deltaTime;
        if (direction == FORWARD)
            Position += Front * velocity;
        if (direction == BACKWARD)
            Position -= Front * velocity;
        if (direction == LEFT)
            Position -= Right * velocity;
        if (direction == RIGHT)
            Position += Right * velocity;
    }

    // 处理从鼠标输入系统接收的输入。期望x和y方向上的偏移值。
    void ProcessMouseMovement(float xoffset, float yoffset, bool constrainPitch = true)
    {
        xoffset *= MouseSensitivity;
        yoffset *= MouseSensitivity;

        Yaw   += xoffset;
        Pitch += yoffset;

        // 确保当 俯仰角 出界时,屏幕不会被翻转
        if (constrainPitch)
        {
            if (Pitch > 89.0f)
                Pitch = 89.0f;
            if (Pitch < -89.0f)
                Pitch = -89.0f;
        }

        // 用欧拉角更新 Front, Right and Up 向量
        updateCameraVectors();
    }

    // 处理从鼠标滚轮事件接收的输入。只需要输入垂直轮轴
    void ProcessMouseScroll(float yoffset)
    {
        Zoom -= (float)yoffset;
        if (Zoom < 1.0f)
            Zoom = 1.0f;
        if (Zoom > 45.0f)
            Zoom = 45.0f;
    }

private:
    // 从相机的欧拉角度计算前方矢量
    void updateCameraVectors()
    {
        // 计算新的Front向量
        QVector3D front;
        front.setX ( cos( qDegreesToRadians(Yaw) ) * cos( qDegreesToRadians(Pitch) ) );
        front.setY ( sin( qDegreesToRadians(Pitch)) );
        front.setZ ( sin( qDegreesToRadians(Yaw) ) * cos( qDegreesToRadians(Pitch) ) );
        Front = front.normalized ();
        // 也重新计算右和向上向量
        Right =  QVector3D::crossProduct (WorldUp,Front).normalized ();
        Up    = QVector3D::crossProduct( Front, Right).normalized ();
    }
};
#endif

当代码中使用了 camera 以后,投射到屏幕上的3轴显示除了熟悉的朝向,z 轴的正方向指向屏幕外,并且符合右手法。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值