最终效果
头文件
#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_5_Core>
#include <QWheelEvent>
#include <QMouseEvent>
#include <QOpenGLShaderProgram>
#include "glcamera.h"
class GLWidget : public QOpenGLWidget,public QOpenGLFunctions_4_5_Core
{
Q_OBJECT
public:
explicit GLWidget(QWidget *parent=nullptr);
~GLWidget();
protected:
void iniDatas();
void initializeGL(); //初始化相关的操作全在这个函数中完成
void resizeGL(int w,int h);
void paintGL();
float *getCylinderVertex(int segment, float r1, float r2, int &count);
int *getCylinderIndices(int segment, int &count);
void wheelEvent(QWheelEvent *pEvent);
void mousePressEvent(QMouseEvent *pEvent);
void mouseMoveEvent(QMouseEvent *pEvent);
void mouseReleaseEvent(QMouseEvent *pEvent);
private:
QOpenGLShaderProgram *m_pShaderProgram = nullptr;
GLCamera *m_pCamera = nullptr;
QMatrix4x4 m_mat4Model;
QPoint m_pointMouseDown;
Qt::MouseButton m_mouseBtn;
int m_nDataCount = 0;
};
#endif // GLWIDGET_H
#include "glwidget.h"
#include <QOpenGLBuffer>
#include <QtMath>
#include <QDebug>
#define BUFFER_OFFSET(offset) ((void*)(offset))
#define BALL_X_SEGMENT 40
#define BALL_Y_SEGMENT 50
GLuint VAO = -1;
GLWidget::GLWidget(QWidget *parent):
QOpenGLWidget(parent)
{
}
GLWidget::~GLWidget()
{
}
void GLWidget::iniDatas()
{
int nIndicesCount = 0;
int nDataCount = 0;
float *vertices = getCylinderVertex(BALL_X_SEGMENT,0.6f,0.8f,nDataCount);
int *indices = getCylinderIndices(BALL_X_SEGMENT,nIndicesCount);
glGenVertexArrays(1,&VAO);
glBindVertexArray(VAO);
GLuint VBO;
glGenBuffers(1,&VBO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices) * nDataCount,
vertices,GL_STATIC_DRAW);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,sizeof(float) * 3,BUFFER_OFFSET(0));
glEnableVertexAttribArray(0);
GLuint EBO;
glGenBuffers(1,&EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices) * nIndicesCount,indices,GL_STATIC_DRAW);
glBindVertexArray(0);//解绑
glBindBuffer(GL_ARRAY_BUFFER,0);
m_nDataCount = nIndicesCount;
// glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);//填充图
// glPolygonMode(GL_FRONT_AND_BACK,GL_POINT);//散点图
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);//线框图
}
void GLWidget::initializeGL()
{
initializeOpenGLFunctions();
m_pShaderProgram = new QOpenGLShaderProgram(this);
m_pShaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex,":/shaders/vertext.vert");
m_pShaderProgram->addShaderFromSourceFile(QOpenGLShader::Fragment,":/shaders/fragment.frag");
m_pShaderProgram->link();
m_pShaderProgram->bind();
m_pCamera = new GLCamera(this->width() * 1.0/this->height());
iniDatas();
}
void GLWidget::resizeGL(int w, int h)
{
glViewport(0,0,w,h);
}
void GLWidget::paintGL()
{
static const GLfloat color[] = {0.0f,0.0f,0.0f,1.0f};
glClearBufferfv(GL_COLOR,0,color);
if(VAO == -1){
return;
}
m_pShaderProgram->setUniformValue("model",m_mat4Model);
m_pShaderProgram->setUniformValue("view",m_pCamera->getCameraMatrix());
glUseProgram(m_pShaderProgram->programId());
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES,m_nDataCount,GL_UNSIGNED_INT,0);
glBindVertexArray(0);
update();
}
float *GLWidget::getCylinderVertex(int segment, float r1, float r2,int &count)
{
float alpha = 2 * M_PI / segment;
count = (segment + 1) * 3 * 4;
float *data = new float[count];
int a = 2;
int b = 1;
int c = 0;
int nIndex = 0;
for (int i = 0; i <= segment; ++i) {
data[nIndex + a] = r1 * qSin(alpha * i);
data[nIndex + b] = r1 * qCos(alpha * i);
data[nIndex + c] = -r2;
nIndex += 3;
}
for (int i = 0; i <= segment; ++i) {
data[nIndex + a] = r2 * qSin(alpha * i);
data[nIndex + b] = r2 * qCos(alpha * i);
data[nIndex + c] = -r2;
nIndex += 3;
}
for (int i = 0; i <= segment; ++i) {
data[nIndex + a] = r1 * qSin(alpha * i);
data[nIndex + b] = r1 * qCos(alpha * i);
data[nIndex + c] = r2;
nIndex += 3;
}
for (int i = 0; i <= segment; ++i) {
data[nIndex + a] = r2 * qSin(alpha * i);
data[nIndex + b] = r2 * qCos(alpha * i);
data[nIndex + c] = r2;
nIndex += 3;
}
return data;
}
int *GLWidget::getCylinderIndices(int segment,int &count)
{
count = segment * 6 * 4;
int *indices = new int[count];
int nIndex = 0;
//第一个圆环
for (int i = 0; i < segment; ++i) {
indices[nIndex] = i;
indices[nIndex + 1] = segment + (i + 1);
indices[nIndex + 2] = i + 1;
indices[nIndex + 3] = i + 1;
indices[nIndex + 4] = segment + (i + 1);
indices[nIndex + 5] = segment + (i + 2);
nIndex += 6;
}
//第一层形成柱 0,2
for (int i = 0; i < segment; ++i) {
indices[nIndex] = i;
indices[nIndex + 1] = segment * 2 + i + 2;
indices[nIndex + 2] = i + 1;
indices[nIndex + 3] = i + 1;
indices[nIndex + 4] = segment * 2 + (i + 2);
indices[nIndex + 5] = segment * 2 + (i + 3);
nIndex += 6;
}
//第二个圆环
for (int i = 0; i < segment; ++i) {
indices[nIndex] = i + (segment * 2 + 2);
indices[nIndex + 1] = segment * 3 + (i + 3);
indices[nIndex + 2] = i + 1 + (segment * 2 + 2);
indices[nIndex + 3] = i + 1 + (segment * 2 + 2);
indices[nIndex + 4] = segment * 3 + (i + 3);
indices[nIndex + 5] = segment * 3 + (i + 4);
nIndex += 6;
}
//第二层形成柱 1,3
for (int i = 0; i < segment; ++i) {
indices[nIndex] = i + segment + 1;
indices[nIndex + 1] = segment * 3 + (i + 3);
indices[nIndex + 2] = i + 1 + segment + 1;
indices[nIndex + 3] = i + 1 + segment + 1;
indices[nIndex + 4] = segment * 3 + (i + 3);
indices[nIndex + 5] = segment * 3 + (i + 4);
nIndex += 6;
}
return indices;
}
void GLWidget::wheelEvent(QWheelEvent *pEvent)
{
if(!m_pCamera){
return;
}
if(pEvent->delta() > 0){//向上滚动,放大
m_pCamera->adjustFocus(1.2f);
}else{
m_pCamera->adjustFocus(1/1.2f);
}
update();
QOpenGLWidget::wheelEvent(pEvent);
}
void GLWidget::mousePressEvent(QMouseEvent *pEvent)
{
m_pointMouseDown = pEvent->pos();
m_mouseBtn = pEvent->button();
}
void GLWidget::mouseMoveEvent(QMouseEvent *pEvent)
{
QPoint pos = pEvent->pos();
QVector2D offset(pos.x() - m_pointMouseDown.x(),
pos.y() - m_pointMouseDown.y());
m_pointMouseDown = pos;
if(m_mouseBtn == Qt::LeftButton){
int angleX = offset.x() / width() * 180;
int angleY = offset.y() / width() * 90;
m_pCamera->rotate(angleX,angleY);
}else{
m_pCamera->translate(-offset.x() / this->width() * 5,-offset.y() / this->height() * 5);
}
}
void GLWidget::mouseReleaseEvent(QMouseEvent *pEvent)
{
m_pointMouseDown = pEvent->pos();
m_mouseBtn = Qt::NoButton;
}
shader文件
#version 450 core
layout(location=0) in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
void main()
{
gl_Position = view * model * vec4(aPos,1);
}