当前位置:网站首页>QT OpenGL moves 3D objects with mouse and keyboard (set camera)
QT OpenGL moves 3D objects with mouse and keyboard (set camera)
2022-07-19 03:41:00 【wb175208】
Set up the camera :
#pragma once
#include <QVector3D>
#include <QMatrix4x4>
class CubeCamera {
public:
CubeCamera();
CubeCamera(QVector3D position,float pitch, float yaw, QVector3D wordUp);
~CubeCamera();
QMatrix4x4 getViewMatrix();
void wheel(int detal);
float&getZoom() {
return _zoom;
}
void keyPress(int key);
void mouseMove(float detalX, float detalY);
private:
void updateCameraVector();
private:
float _pitch = 0.0;
float _yaw = 0.0;
QVector3D _wordUp;
QVector3D _right;
QVector3D _position = QVector3D(0.0, 0.0, -3.0);
QVector3D _up = QVector3D(0.0, 1.0, 0.0);
QVector3D _front = QVector3D(0.0, 0.0, 0.0);
float _zoom = 45.0;
float _zoomStep = 2.0;
};
#include "CubeCamera.h"
CubeCamera::CubeCamera() {
}
CubeCamera::CubeCamera(QVector3D position, float pitch, float yaw, QVector3D wordUp) {
_position = position;
_pitch = pitch;
_yaw = yaw;
_wordUp = wordUp;
updateCameraVector();
}
CubeCamera::~CubeCamera() {
}
QMatrix4x4 CubeCamera::getViewMatrix() {
QMatrix4x4 viewMatrix;
viewMatrix.lookAt(_position, _position + _front, _up);
return viewMatrix;
}
void CubeCamera::wheel(int detal) {
if (detal < 0){
_zoom += _zoomStep;
if (_zoom >= 60.0){
_zoom = 60.0;
}
} else {
_zoom -= _zoomStep;
if (_zoom <= 1.0){
_zoom = 1.0;
}
}
}
void CubeCamera::keyPress(int key) {
if (key == Qt::Key_A) {
_position += _right * 0.1;
} else if (key == Qt::Key_D) {
_position -= _right * 0.1;
} else if (key == Qt::Key_W) {
_position -= _wordUp * 0.1;
} else if (key == Qt::Key_S) {
_position += _wordUp * 0.1;
} else if (key == Qt::Key_E) {
_position += _front *0.1;
} else if (key == Qt::Key_Q) {
_position -= _front *0.1;
}
}
void CubeCamera::mouseMove(float xoffset, float yoffset) {
xoffset *= 0.005;
yoffset *= 0.005;
qDebug() << xoffset<< yoffset;
_yaw -= xoffset;
_pitch += yoffset;
if (_pitch > 89.0f)
_pitch = 89.0f;
if (_pitch < -89.0f)
_pitch = -89.0f;
updateCameraVector();
}
void CubeCamera::updateCameraVector() {
QVector3D front;
front.setX(cos(_yaw) * cos(_pitch));
front.setY(sin(_pitch));
front.setZ(sin(_yaw) * cos(_pitch));
_front = front.normalized();
_right = QVector3D::crossProduct(_front, _wordUp).normalized();
_up = QVector3D::crossProduct(_right, _front).normalized();
}
#pragma once
#include <QOpenGLWindow>
#include <QOpenGLExtraFunctions>
#include <QDebug>
#include <QOpenGLTexture>
#include <QElapsedTimer>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
class RotateCubeWnd : public QOpenGLWindow{
Q_OBJECT
public:
RotateCubeWnd();
~RotateCubeWnd();
protected:
void initializeGL()override;
void paintGL()override;
void keyPressEvent(QKeyEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
private slots:
void slotTimeOut();
private:
GLuint _VBO, _VAO;
class QOpenGLFunctions_3_3_Core* _openGLCore;
QOpenGLShaderProgram _shaderProgram;// Shader program , All shaders in the system
class QOpenGLTexture *_texture1;
QMatrix4x4 model,view, projection;
class QTimer* _timer = nullptr;
double _angle = 30.0;
class CubeCamera* _cubeCamera = nullptr;
bool _lBtnDown = false;
QPoint _lBtnDownPos;
};
#include "RotateCubeWnd.h"
#include <QKeyEvent>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QTimer>
#include <QOpenGLFunctions_3_3_Core>
#include "CubeCamera.h"
RotateCubeWnd::RotateCubeWnd(){
_timer = new QTimer;
_timer->start(20);
connect(_timer, SIGNAL(timeout()), this, SLOT(slotTimeOut()));
_cubeCamera = new CubeCamera(QVector3D(0.0, 0.0, -4.0), 0.0, 90.0, QVector3D(0.0, 1.0, 0.0));
}
RotateCubeWnd::~RotateCubeWnd(){
}
void RotateCubeWnd::initializeGL() {
_openGLCore = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
// Open depth test
_openGLCore->glEnable(GL_DEPTH_TEST);
_openGLCore->glDepthFunc(GL_LESS);
GLfloat vertexData[] = {
// X Y Z U V
// Next
-1.0f,-1.0f,-1.0f, 0.0f, 0.0f,
1.0f,-1.0f,-1.0f, 1.0f, 0.0f,
-1.0f,-1.0f, 1.0f, 0.0f, 1.0f,
1.0f,-1.0f,-1.0f, 1.0f, 0.0f,
1.0f,-1.0f, 1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f, 0.0f, 1.0f,
// On
-1.0f, 1.0f,-1.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f,-1.0f, 1.0f, 0.0f,
1.0f, 1.0f,-1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
// front
-1.0f,-1.0f, 1.0f, 1.0f, 0.0f,
1.0f,-1.0f, 1.0f, 0.0f, 0.0f,
-1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
// after
-1.0f,-1.0f,-1.0f, 0.0f, 0.0f,
-1.0f, 1.0f,-1.0f, 0.0f, 1.0f,
1.0f,-1.0f,-1.0f, 1.0f, 0.0f,
1.0f,-1.0f,-1.0f, 1.0f, 0.0f,
-1.0f, 1.0f,-1.0f, 0.0f, 1.0f,
1.0f, 1.0f,-1.0f, 1.0f, 1.0f,
// Left
-1.0f,-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, 1.0f,-1.0f, 1.0f, 0.0f,
-1.0f,-1.0f,-1.0f, 0.0f, 0.0f,
-1.0f,-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f, 1.0f, 0.0f,
// Right
1.0f,-1.0f, 1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f, 1.0f, 0.0f,
1.0f, 1.0f,-1.0f, 0.0f, 0.0f,
1.0f,-1.0f, 1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 0.0f, 1.0f
};
_openGLCore->glGenVertexArrays(1, &_VAO);
_openGLCore->glGenBuffers(1, &_VBO);
_openGLCore->glBindVertexArray(_VAO);
_openGLCore->glBindBuffer(GL_ARRAY_BUFFER, _VBO);
_openGLCore->glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
// Location properties
_openGLCore->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
_openGLCore->glEnableVertexAttribArray(0);
// Coordinate properties
_openGLCore->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
_openGLCore->glEnableVertexAttribArray(1);
// Vertical mirror mirrored
_texture1 = new QOpenGLTexture(QImage("E:/Projects/QtGuiTest/OPenGLApp/RotateCube/a.jpg").mirrored());
if (!_texture1->isCreated()) {
qDebug() << "Failed to load texture";
}
_texture1->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
_texture1->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);
_texture1->setMinificationFilter(QOpenGLTexture::Linear);
_texture1->setMagnificationFilter(QOpenGLTexture::Linear);
_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex, "E:/Projects/QtGuiTest/OPenGLApp/RotateCube/RotateCube.vert");
_shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment, "E:/Projects/QtGuiTest/OPenGLApp/RotateCube/RotateCube.frag");
_shaderProgram.link();
_shaderProgram.bind();
_shaderProgram.setUniformValue("textureImg", 0);
model.rotate(45.0, QVector3D(1.0, 1.0, 1.0));
model.scale(0.5);
view = _cubeCamera->getViewMatrix();
}
void RotateCubeWnd::paintGL() {
_openGLCore->glClearColor(0.4f, 0.4f, 0.4f, 1.0f);
_openGLCore->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_openGLCore->glActiveTexture(GL_TEXTURE0);
_texture1->bind();
_shaderProgram.bind();
#if 0
QMatrix4x4 view;
/* The first parameter is equivalent to changing the observation position of the camera , Changing this value regularly can have the effect of observing objects from different angles . Changing the second parameter is equivalent to changing the origin of the world coordinate system , Objects in the whole world coordinate system will move with them . */
view.lookAt(QVector3D(0.0f, 0.0f, -3.0f), QVector3D(0.0, 0.0, 0.0), QVector3D(0.0, 1.0, 0.0));
view.rotate(_angle, QVector3D(0.0, 1.0, 0.0));
#else
QMatrix4x4 view = _cubeCamera->getViewMatrix();
#endif
QMatrix4x4 projection;
projection.perspective(_cubeCamera->getZoom(), width() / height(), 0.1, 100);
_shaderProgram.setUniformValue("model", model);
_shaderProgram.setUniformValue("view", view);
_shaderProgram.setUniformValue("projection", projection);
/* Cube 6 Face to face , Each side has 2 Triangles , Each triangle has 3 vertices , So the number of vertices to paint is :6 × 2 × 3 = 36 */
_openGLCore->glDrawArrays(GL_TRIANGLES, 0, 36);
update();
}
void RotateCubeWnd::keyPressEvent(QKeyEvent *event) {
_cubeCamera->keyPress(event->key());
}
void RotateCubeWnd::mouseMoveEvent(QMouseEvent *event) {
if (_lBtnDown){
float xpos = static_cast<float>(event->pos().x());
float ypos = static_cast<float>(event->pos().y());
float xoffset = _lBtnDownPos.x() - xpos;
float yoffset = _lBtnDownPos.y() - ypos;
_lBtnDownPos = event->pos();
_cubeCamera->mouseMove(xoffset, yoffset);
}
}
void RotateCubeWnd::wheelEvent(QWheelEvent *event) {
_cubeCamera->wheel(event->delta());
update();
}
void RotateCubeWnd::mousePressEvent(QMouseEvent *event) {
if (event->button() == Qt::LeftButton){
_lBtnDown = true;
_lBtnDownPos = event->pos();
}
}
void RotateCubeWnd::mouseReleaseEvent(QMouseEvent *event) {
if (event->button() == Qt::LeftButton) {
_lBtnDown = false;
}
}
void RotateCubeWnd::slotTimeOut() {
_angle += 1.0;
//update();
}
#include "OPenGLApp.h"
#include <QtWidgets/QApplication>
#include <QtOpenGL/QtOpenGL>
#include "MyOpenGLWnd.h"
#include "EBOWnd.h"
#include "HelloShader.h"
#include "HelloShaderSelf.h"
#include "TextureWnd.h"
#include "CameraWnd.h"
#include "QOpenGLLight.h"
#include "RotateCube/RotateCubeWnd.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
RotateCubeWnd window;
window.setTitle(QStringLiteral(" This is a OpenGL window "));
window.resize(800, 800);
window.show();
return a.exec();
}
Vertex shader :
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTextureCoord;
out vec3 outColor;
out vec2 textureCoord;
// Matrix must be initialized , Initialize identity matrix , otherwise GLSL The default matrix in the language is 0 matrix
uniform mat4 trans = mat4(1.0);
uniform mat4 model = mat4(1.0);
uniform mat4 view = mat4(1.0);
uniform mat4 projection = mat4(1.0);
void main(){
gl_Position = projection * view * model * vec4(aPos, 1.0);
textureCoord = aTextureCoord;
}
Fragment Shader :
#version 330 core
out vec4 fragColor;
in vec3 outColor;// Color passed from vertex shader
in vec2 textureCoord;
uniform sampler2D textureImg;
void main(){
fragColor = texture(textureImg, textureCoord);
}
aaa
边栏推荐
- MySQL 增删查改(基础)
- 【C语言】0基础教程——文件操作(未完待续)
- [MySQL] MHA high availability
- Edge detection method -- first order edge detection
- Net SNMP development I
- Flutter development: running the flutter upgrade command reports an error exception:flutter failed to create a directory at... Solution
- Monte Carlo based reinforcement learning method [with code implementation]
- 基于Pandoc与VSCode的 LaTeX环境配置
- ResNet
- 374. 猜数字大小(入门 必会)
猜你喜欢
leetcode:50. Pow(x, n)
Monte Carlo based reinforcement learning method [with code implementation]
机器学习库Scikit-Learn(线性模型、岭回归、插入一列数据(insert)、提取所需列、向量机(SVM)、聚类)
Thinkphp5.0模型操作使用page进行分页
Through openharmony compatibility evaluation, the big brother development board and rich teaching and training resources have been ready
Leetcode: dynamic programming [basic problem solving]
367. Effective complete square (necessary for entry)
Neural network learning notes 2.2 -- write a simple convolution neural network image classifier with MATLAB
神经网络学习笔记2.2 ——用Matlab写一个简单的卷积神将网络图像分类器
Properties of Gaussian distribution (including code)
随机推荐
MySQL log management and full backup incremental backup and recovery
367. Effective complete square (necessary for entry)
oracle 查询 主机名和对应的IP地址
論文閱讀:U-Net++: Redesigning Skip Connections to Exploit Multiscale Features in Image Segmentation
机器学习库Scikit-Learn(线性模型、岭回归、插入一列数据(insert)、提取所需列、向量机(SVM)、聚类)
ulsm配置案例
ResNet
The installation software prompts that the program input point adddlldirectory cannot be located in the dynamic link library kernel32 DLL (download address at the end of the text)
S32k148evb about eNet loopback experiment
Go语言中的Iota关键字怎么使用
The third day of the three questions of Luogu daily (make up on the fourth day)
HRNet
leetcode:78. subset
Dive into deep learning - 2.2 data preprocessing
Shell script receives and returns parameters
Theoretical basis of double Q-learning and its code implementation [pendulum-v0]
[2016 CCPC 杭州J] Just a Math Problem (莫比乌斯反演)
如何将Excel中的数据粘贴到cxGrid中
[MySQL] data query operation (select statement)
By voting for the destruction of STI by Dao, seektiger is truly community driven