您的位置:首页 > 编程语言 > Qt开发

OpenGL+Qt界面(三) Qt中实现OPENGL的基本交互+代码

2017-10-18 20:53 4035 查看
开发环境

实现结果

实现步骤

具体实现与代码
增加交互函数

修改simplevert

设置uniform变量

新增shader

新增shaderProgram

设置坐标shader的uniform

工程文件

参考

开发环境

vs2015+Qt5

实现结果

依赖于Qt的的一个界面,能够进行一定的交互和显示坐标轴



实现步骤

实现物体的移动

- 重新定义鼠标交互函数

- 修改shader文件,增加uniform变量

- 设置uniform变量

* 增加坐标轴*

- 新增shader

- 新增shaderProgram

- 设置unifom

具体实现与代码

1 增加交互函数

scenewindow.hpp

//新增函数
protected:
void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
//新增交互变量
private:
QCursor cursor; // 管理光标形状
QVector3D cameraPos = QVector3D(0.0f, 0.0f, 3.0f);    //相机位置
QVector3D worldCentrol = QVector3D(0.0f, 0.0f, 0.0f); //世界坐标原点,相机朝向
QVector3D cameraUp = QVector3D(0.0f, 1.0f, 0.0f);     //相机的顶部朝向y轴
QVector3D transVec = QVector3D(0.0f, 0.0f, 0.0f);     //局部坐标在世界坐标中的平移量(构建ModelMatrix,进行“局部空间”到“世界空间”的转换)

GLfloat yaw = 0.0f;       //偏航角
GLfloat pitch = 0.0f;     //俯仰角
GLfloat lastX = 0;        //光标上次x值
GLfloat lastY = 0;        //光标上次y值


scenewindow.cpp

在构造函数中新增

cursor.setShape(Qt::ArrowCursor);
setCursor(cursor);


增加交互函数

void SceneWindow::mouseMoveEvent(QMouseEvent *event)
{
//鼠标左键用来实现对物体的旋转功能
if (event->buttons() == Qt::LeftButton)
{
//设置光标形状
cursor.setShape(Qt::ClosedHandCursor);
setCursor(cursor);
//计算yaw,pitch值的改变量
GLfloat xoffset = event->x() - lastX;
GLfloat yoffset = event->y() - lastY;
lastX = event->x();
lastY = event->y();

GLfloat sensitivity = 0.4f; //旋转时的灵敏度
xoffset *= sensitivity;
yoffset *= sensitivity;

yaw += xoffset;
pitch += yoffset;

//可以用来设置俯仰角的上下界
if (pitch > 89.0f)
pitch = 89.0f;
if (pitch < -89.0f)
pitch = -89.0f;
}
//鼠标右键用来实现对移动物体(即局部坐标在世界坐标中的移动)
else if (event->buttons() == Qt::RightButton)
{
//计算x,y方向的偏移量
GLfloat xoffset = event->x() - lastX;
GLfloat yoffset = event->y() - lastY;
lastX = event->x();
lastY = event->y();

GLfloat sensitivity = 0.01f; //移动时的灵敏度
xoffset *= sensitivity;
yoffset *= sensitivity;

//仅需在x-y平面内移动即可
transVec += QVector3D(xoffset, -yoffset, 0.0f);
}
}

//滚轮实现对物体的放大缩小,摄像机距离远近(放大缩小)
void SceneWindow::wheelEvent(QWheelEvent *event)
{
GLfloat sensitivity = 0.0005f;
cameraPos *= (1.0f - event->delta() * sensitivity);
}

void SceneWindow::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
//设置光标形状
cursor.setShape(Qt::PointingHandCursor);
setCursor(cursor);
}
else if (event->button() == Qt::RightButton)
{
//设置光标形状
cursor.setShape(Qt::SizeAllCursor);
setCursor(cursor);
}
//记录点击光标时的位置
lastX = event->x();
lastY = event->y();
}

void SceneWindow::mouseReleaseEvent(QMouseEvent *event)
{
//设置光标形状
cursor.setShape(Qt::ArrowCursor); setCursor(cursor);
}


2 修改simple.vert

simple.vert

#version 330 core
layout(location = 0) in vec3 vPosition;
layout(location = 1) in vec3 vColor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec3 Color;
void main()
{
gl_Position = projection * view * model * vec4(vPosition, 1.0);
Color = vColor;
}


3 设置uniform变量

在paintGL中增加

//渲染彩色正方体
shaderCube.bind();
QMatrix4x4 view;
QMatrix4x4 projection;
QMatrix4x4 model;
view.lookAt(cameraPos, worldCentrol, cameraUp);
projection.perspective(45.0f, 4.0f / 3.0f, 0.1f, 100000.0f);
model.translate(transVec);
model.rotate(pitch, 1.0f, 0.0f, 0.0f);  //按住左键,上下拖动鼠标让立方体绕x轴旋转
model.rotate(yaw, 0.0f, 1.0f, 0.0f);    //按住左键,左右拖动鼠标让立方体绕y轴旋转
shaderCube.setUniformValue("view", view);
shaderCube.setUniformValue("projection", projection);
shaderCube.setUniformValue("model", model);

glBindVertexArray(IDVAO[0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);


4 新增shader

在shader文件中新增一个coordinate.vert 的文件

#version 330 core
layout(location = 0) in vec3 vPosition;
layout(location = 1) in vec3 vColor;
out vec3 Color;
uniform mat4 modelCoor;
uniform mat4 viewCoor;
uniform mat4 projectionCoor;

void main()
{
Color = vColor;
gl_Position = projectionCoor * viewCoor * modelCoor * vec4(vPosition,1.0);
}


5 新增shaderProgram

在SceneWindow中新增私有变量:

QOpenGLShaderProgram shaderCoor;

在initializeGL中增加

//初始化坐标着色器程序
shaderCoor.addShaderFromSourceFile(QOpenGLShader::Vertex, "shader/coordinate.vert");
shaderCoor.addShaderFromSourceFile(QOpenGLShader::Fragment, "shader/simple.frag");
shaderCoor.link();
//新增坐标
//绘制坐标数据
GLfloat coorVertices[] =
{
0.0f,  0.0f,  0.0f,  1.0f, 0.0f, 0.0f,
0.05f, 0.0f,  0.0f,  1.0f, 0.0f, 0.0f,
0.0f,  0.0f,  0.0f,  0.0f, 1.0f, 0.0f,
0.0f,  0.05f, 0.0f,  0.0f, 1.0f, 0.0f,
0.0f,  0.0f,  0.0f,  0.0f, 0.0f, 1.0f,
0.0f,  0.0f,  0.05f, 0.0f, 0.0f, 1.0f
};
// 绑定 VAO VBO
/* 显示坐标信息 */
glBindVertexArray(IDVAO[1]);    //开始记录状态信息
glBindBuffer(GL_ARRAY_BUFFER, IDVBO[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(coorVertices), coorVertices, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);

glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);

glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindVertexArray(0);           //结束记录状态信息


6 设置坐标shader的uniform

在paintGL函数中新增

shaderCoor.bind();
QMatrix4x4 viewCoor1;
QMatrix4x4 projectionCoor1;
QMatrix4x4 modelCoor1;
viewCoor1.lookAt(cameraPos, worldCentrol, cameraUp);
projectionCoor1.perspective(45.0f, 5.0f / 3.0f, 0.1f, 100000.0f);
//modelCoor1.translate(QVector3D(-0.48f, -0.28f, cameraPos1.length()-0.8f));
modelCoor1.setToIdentity();
modelCoor1.translate(QVector3D(-0.48f, -0.28f, cameraPos.length() - 0.8f));
modelCoor1.rotate(pitch, 1.0f, 0.0f, 0.0f);
modelCoor1.rotate(yaw, 0.0f, 1.0f, 0.0f);

shaderCoor.setUniformValue("viewCoor", viewCoor1);
shaderCoor.setUniformValue("projectionCoor", projectionCoor1);
shaderCoor.setUniformValue("modelCoor", modelCoor1);

glBindVertexArray(IDVAO[1]);
glDrawArrays(GL_LINES, 0, 2);
glDrawArrays(GL_LINES, 2, 2);
glDrawArrays(GL_LINES, 4, 2);
glBindVertexArray(0);


工程文件

百度云链接: https://pan.baidu.com/s/1c2wC3By 密码: m271

下一篇 Qt+OpenGL(五) 纹理贴图

参考

如何在Qt5中嵌入一个OpenGL程序部件

QOpenGLShaderProgram文档

QMatrix4x4 文档
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  qt opengl