首页 > 其他分享 >Qt3D改变观察视角例程(二)

Qt3D改变观察视角例程(二)

时间:2023-11-03 11:16:04浏览次数:36  
标签:10.0 视角 1.0 例程 void Qt3D program QVector3D vec3

本例依旧是改变3D视角。不同的是这个是视野位置不变而只改变观察方向。相当于一个人站在原地不动,旋转脑袋看周围的东西。测试的条件是VS2017和Qt5.9。主要的知识点就是欧拉角的计算。下面是效果图:

头文件:

class QOpenGLTexture;
class QOpenGLBuffer;

class MvOpenGLWidget : public QOpenGLWidget, private QOpenGLFunctions
{
    Q_OBJECT

private:
    struct VertexData
    {
        QVector3D pos;
        QVector3D normal;
        QVector3D color;
    };

public:
    MvOpenGLWidget(QWidget* parent = 0);

private:
    void initializeGL() override;
    void paintGL() override;
    void resizeGL(int w, int h) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    QVector3D calcDirVec() const;

private:
    QOpenGLShaderProgram* program;
    QOpenGLBuffer* vertexBuff;
    QOpenGLBuffer* indexBuff;
    /* 下面2个是相机方向,都为0时相机朝向X轴正方向 */
    float yaw; /* 绕Y轴旋转 */
    float pitch; /* 绕X轴旋转 */
    /* 下面1个是鼠标上次点击的位置 */
    QPoint lastPos;
};

CPP文件:

MvOpenGLWidget::MvOpenGLWidget(QWidget* parent) :
    QOpenGLWidget(parent), lastPos(0xDEADBEEFi32, 0xDEADBEEFi32)
{
    yaw = -90.0f;
    pitch = 0;

    QSurfaceFormat surface;
    surface.setSamples(4);
    setFormat(surface);
}

void MvOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();
    glEnable(GL_DEPTH_TEST);

    program = new QOpenGLShaderProgram(this);
    const char* vsrc = u8R"(
        #version 330 core
        layout (location = 0) in vec3 aPos; // 空间坐标
        layout (location = 1) in vec3 aNormal; // 法线向量
        layout (location = 2) in vec3 aColor; // 顶点颜色
        uniform mat4 modelMatrix;
        uniform mat4 mvpMatrix;
        out vec3 oNormal;
        out vec3 oFragPos;
        out vec3 oColor;

        void main()
        {
            oFragPos = vec3(modelMatrix * vec4(aPos, 1.0));
            oNormal =  mat3(transpose(inverse(modelMatrix))) * aNormal;
            oColor = aColor;
            gl_Position = mvpMatrix * vec4(aPos, 1.0);
        })";
    program->addShaderFromSourceCode(QOpenGLShader::Vertex, vsrc);
    const char* fsrc = u8R"(
        #version 330 core
        uniform vec3 lightPos; 
        uniform vec3 viewPos; 
        uniform vec3 lightColor;
        in vec3 oNormal;
        in vec3 oFragPos;
        in vec3 oColor;

        void main()
        {
            // 环境光照
            float ambientStrength = 0.4;
            vec3 ambient = ambientStrength * lightColor;
            // 漫反射光照 
            vec3 norm = normalize(oNormal);
            vec3 lightDir = normalize(lightPos - oFragPos);
            float diff = max(dot(norm, lightDir), 0.0);
            vec3 diffuse = diff * lightColor;
            // 镜面光照
            float specularStrength = 1.0;
            vec3 viewDir = normalize(viewPos - oFragPos);
            vec3 reflectDir = reflect(-lightDir, norm);
            float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0);
            vec3 specular = specularStrength * spec * lightColor;
            // 把纹理中的颜色和光照参数相乘
            gl_FragColor = vec4((ambient + diffuse + specular) * oColor, 1.0);
        })";
    program->addShaderFromSourceCode(QOpenGLShader::Fragment, fsrc);

    program->link();
    program->bind();

    VertexData vertices[] =
    {
        { QVector3D(-0.433f, 0, -0.25f), QVector3D(-0.816f, 0.333f, 0.471f), QVector3D(1.0f, 0, 0) },
        { QVector3D(0, 0, 0.5f), QVector3D(-0.816f, 0.333f, 0.471f), QVector3D(0, 1.0f, 0) },
        { QVector3D(0, 0.707f, 0), QVector3D(-0.816f, 0.333f, 0.471f), QVector3D(0, 0, 1.0f) },

        { QVector3D(0, 0, 0.5f), QVector3D(0.816f, 0.333f, 0.471f), QVector3D(1.0f, 1.0f, 0) },
        { QVector3D(0.433f, 0, -0.25f), QVector3D(0.816f, 0.333f, 0.471f), QVector3D(1.0f, 0, 1.0f) },
        { QVector3D(0, 0.707f, 0), QVector3D(0.816f, 0.333f, 0.471f), QVector3D(0, 1.0f, 1.0f) },

        { QVector3D(0.433f, 0, -0.25f), QVector3D(0, 0.333f, -0.943f), QVector3D(0, 0, 1.0f) },
        { QVector3D(-0.433f, 0, -0.25f), QVector3D(0, 0.333f, -0.943f), QVector3D(0, 1.0f, 0) },
        { QVector3D(0, 0.707f, 0), QVector3D(0, 0.333f, -0.943f), QVector3D(1.0f, 0, 0) },

        { QVector3D(0, 0, 0.5f), QVector3D(0, -1.0f, 0), QVector3D(0, 1.0f, 1.0f) },
        { QVector3D(-0.433f, 0, -0.25f), QVector3D(0, -1.0f, 0), QVector3D(1.0f, 1.0f, 0) },
        { QVector3D(0.433f, 0, -0.25f), QVector3D(0, -1.0f, 0), QVector3D(1.0f, 0, 1.0f) },

        /* 后面6个点绘制水平的地面 */
        { QVector3D(-10.0f, -0.2f, -10.0f), QVector3D(0, 1.0f, 0), QVector3D(0, 1.0f, 1.0f) },
        { QVector3D(-10.0f, -0.2f, 10.0f), QVector3D(0, 1.0f, 0), QVector3D(1.0f, 1.0f, 0) },
        { QVector3D(10.0f, -0.2f, -10.0f), QVector3D(0, 1.0f, 0), QVector3D(1.0f, 0, 1.0f) },

        { QVector3D(10.0f, -0.2f, -10.0f), QVector3D(0, 1.0f, 0), QVector3D(0, 1.0f, 1.0f) },
        { QVector3D(-10.0f, -0.2f, 10.0f), QVector3D(0, 1.0f, 0), QVector3D(1.0f, 1.0f, 0) },
        { QVector3D(10.0f, -0.2f, 10.0f), QVector3D(0, 1.0f, 0), QVector3D(1.0f, 0, 1.0f) },
    };
    GLushort indices[] =
    {
        0, 1, 2, 3, 4, 5,
        6, 7, 8, 9, 10, 11,
        12, 13, 14, 15, 16, 17,
    };
    vertexBuff = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
    vertexBuff->create();
    vertexBuff->bind();
    vertexBuff->allocate(vertices, 18 * sizeof(VertexData));
    indexBuff = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
    indexBuff->create();
    indexBuff->bind();
    indexBuff->allocate(indices, 18 * sizeof(float));

    int offset = 0;
    int vertexLocation = program->attributeLocation("aPos");
    program->enableAttributeArray(vertexLocation);
    program->setAttributeBuffer(vertexLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
    offset += sizeof(QVector3D);
    int normalLocation = program->attributeLocation("aNormal");
    program->enableAttributeArray(normalLocation);
    program->setAttributeBuffer(normalLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
    offset += sizeof(QVector3D);
    int colorLocation = program->attributeLocation("aColor");
    program->enableAttributeArray(colorLocation);
    program->setAttributeBuffer(colorLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
}

#define LIGHT_COLOR QVector3D(0.9f, 1.0f, 2.0f) /* 这里的颜色值可以大于1不知道为什么 */
#define LIGHT_POS   QVector3D(2.5f, 5.8f, 2.0f)
#define VIEW_CENTER QVector3D(0.0f, 0.25f, 0.0f)

void MvOpenGLWidget::paintGL()
{
    QMatrix4x4 projection;
    projection.perspective(45.0f, 1, 0.1f, 100.0f);
    QMatrix4x4 viewMatrix;
    QVector3D eyeDir = calcDirVec();
    QVector3D eyePos = VIEW_CENTER - 10 * eyeDir;
    viewMatrix.lookAt(eyePos, VIEW_CENTER, QVector3D(0, 1, 0));
    QMatrix4x4 modelMatrix;
    modelMatrix.translate(0, -0.8, 0); // 平移
    modelMatrix.rotate(0, 0, 1); // 旋转
    modelMatrix.scale(4.0); // 缩放
    QMatrix4x4 mvpMatrix = projection * viewMatrix * modelMatrix;

    program->setUniformValue("lightColor", LIGHT_COLOR);
    program->setUniformValue("lightPos", LIGHT_POS);
    program->setUniformValue("viewPos", eyePos);
    program->setUniformValue("mvpMatrix", mvpMatrix);
    program->setUniformValue("modelMatrix", modelMatrix);
    glDrawElements(GL_TRIANGLES, 18, GL_UNSIGNED_SHORT, 0);
}

#undef LIGHT_COLOR
#undef LIGHT_POS
#undef EYE_CENTER

void MvOpenGLWidget::resizeGL(int w, int h)
{
}

void MvOpenGLWidget::mousePressEvent(QMouseEvent *event)
{
    lastPos = event->pos();
}

void MvOpenGLWidget::mouseReleaseEvent(QMouseEvent *event)
{
    lastPos = QPoint(0xDEADBEEFi32, 0xDEADBEEFi32);
}

void MvOpenGLWidget::mouseMoveEvent(QMouseEvent *event)
{
    float xoffset = event->pos().x() - lastPos.x();
    float yoffset = lastPos.y() - event->pos().y();
    lastPos = event->pos();

    float sensitivity = 0.25f;
    xoffset *= sensitivity;
    yoffset *= sensitivity;

    yaw += xoffset;
    pitch += yoffset;
    pitch = std::max(-89.0f, std::min(89.0f, pitch));

    update();
}

QVector3D MvOpenGLWidget::calcDirVec() const
{
    QVector3D front;
    front.setX(cosf(qDegreesToRadians(yaw)) * cosf(qDegreesToRadians(pitch)));
    front.setY(sinf(qDegreesToRadians(pitch)));
    front.setZ(sinf(qDegreesToRadians(yaw)) * cosf(qDegreesToRadians(pitch)));
    return front.normalized();
}

 

标签:10.0,视角,1.0,例程,void,Qt3D,program,QVector3D,vec3
From: https://www.cnblogs.com/mengxiangdu/p/17798167.html

相关文章

  • 一种通用的arduino通信例程
    本教程将给出一种通用的,适用于arduino(uno和mega等)单片机的一个通信的教程,通过对例程的修改,可以做成任意的符合需求的代码,下面请看。//函数定义StringdetectString_openmv();intrecv_order();StringdetectString_openmv()//判断传入的字符串能否被接收{//我们传入......
  • 电机矢量控制算法和例程
    电机矢量控制算法是一种高级的电机控制方法,它通过将电机转子空间矢量转换到旋转坐标系中,并在该坐标系中进行控制来实现对电机的精确控制。下面是对电机矢量控制算法的详细解释:坐标系变换:电机矢量控制首先将电机转子空间矢量变换到一个旋转坐标系中,通常是dq坐标系。dq坐标系是以转子......
  • 基于ZCU104的PS和PL数据交互例程(三):vivado中创建IP
    基于ZCU104的PS和PL数据交互例程(三):vivado中创建IP以创建带有AXI-LITE接口的IP为例子按照下面步骤创建这里注意,这里选择的NumberofRegisters,会在后面的代码里面对应slv_reg0,slv_reg1,...,slv_reg3打开IP目录,右键刚才的IP,选择EidtinIPPackagercontroller_v1_0......
  • 基于ZCU104的PS和PL数据交互例程(二):vivado中封装现有工程成IP
    基于ZCU104的PS和PL数据交互例程(二):vivado中封装现有工程成IP设计DUT功能正常创建一个vivado工程,添加一个dut.v的文件功能:读入100个输入数据,每个数据依次加0,1,2,...,然后输出。比如输入是0到99,则输出是0,2,4,到198,如下图所示。状态机:时序图:端口情况:创建vivado工程正常创建新......
  • Sobel算子详解及例程
    Sobel算子是一种经典的边缘检测算子,被广泛应用于图像处理领域。它基于图像亮度的变化率来检测边缘的位置,主要通过计算图像中像素点的梯度来实现。Sobel算子分为水平和垂直两个方向的算子,记作Gx和Gy。它们分别对图像进行水平和垂直方向的卷积运算,得到对应方向上的梯度值。具体而言,So......
  • 双碳背景下能源消费促进经济增长的影响研究—基于能源转型视角(LW文档)
    (一)选题背景2020年来,突如其来的新冠肺炎疫情给中国经济社会带来了极大的影响。聚焦能源领域,受疫情封控影响导致2020年能源需求量总体呈下滑趋势,进而引发能源供给过剩,价格下跌,投资下滑等一系列连锁式反应。据统计,2020年全球一次能源消费降至约2016年同等水平。随着2021年疫情影响减弱......
  • 转载WIFI小车APP远程控制,无线智能小车之ESP8266例程
    WIFI小车APP远程控制,无线智能小车之ESP8266例程  第一、原理讲解原理简述:利用发布订阅模式,即:利用ESP8266订阅了一个主题,再利用appinventor编写的app往这个主题发布消息,由于ESP8266订阅了这个消息,所以就可以收到app发布得消息,从而执行相应得动作,比如前进\后退\左转\右......
  • 下载的PC游戏启动后报错:无法加载 DLL“steam_api64”: 动态链接库(DLL)初始化例程失败
    无法加载DLL“steam_api64”:动态链接库(DLL)初始化例程失败。(异常来自HRESU解决方式:将文件夹拷贝到Steam-->steamapps文件夹下面还好是忍者神龟抛了个异常,才找到了问题所在,论抛异常的重要性!!!忍者神龟如龙......
  • BLE_HID例程增加报表描述符使用
    我们一般hid类设备都是键鼠设备居多,在此还是以CH582的Hid_keyboard程序为例,修改其中的hidkeyboardservice.c文件,增加了:16bit全键盘、多媒体键(如音量+,音量-,静音等)、系统控制键(电脑休眠、电脑关机),由于蓝牙在部分电脑中休眠期间蓝牙驱动是关闭的,因此无法通过蓝牙唤醒电脑,鼠标数......
  • 技术先驱视角:长城汽车工程师揭秘Hi4技术的无限潜力
    文|智能相对论作者|沈浪汽车行业的变革正在回归平衡和理性,混动市场再度掀起新的浪潮,以Hi4技术为代表的混合动力解决方案备受瞩目,并爆发出无限潜力。日前,工信部等七个部门联合印发了《关于汽车行业稳增长工作方案(2023-2024)》的通知。其中,关于“油车”还是“电车”的态度有了一个......