Qt+OpenGL——参考公开课绘制球

公开课地址:中国大学慕课网——华中科技大学《计算机图形学》

根据老师的课件的代码绘制出来的球只有一面,当把X坐标和Z坐标进行交换就能正常绘制出球。
shader代码参考上一篇博客:Qt+OpenGL——索引绘制四边形

头文件

#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_5_Core>

#include <QOpenGLShaderProgram>

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 *getBallVertex(int xSegment,int ySegment);
    int *getBallIndices(int xSegment,int ySegment);

private:
    QOpenGLShaderProgram *m_pShaderProgram = nullptr;

};

#endif // GLWIDGET_H

源文件

#include "glwidget.h"
#include <QOpenGLBuffer>
#include <QtMath>

#include <QDebug>


#define BUFFER_OFFSET(offset) ((void*)(offset))


#define BALL_X_SEGMENT 50
#define BALL_Y_SEGMENT 50


GLuint VAO = -1;
GLWidget::GLWidget(QWidget *parent):
    QOpenGLWidget(parent)
{

}

GLWidget::~GLWidget()
{

}

void GLWidget::iniDatas()
{

    float *vertices = getBallVertex(BALL_X_SEGMENT,BALL_Y_SEGMENT);
    int *indices = getBallIndices(BALL_X_SEGMENT,BALL_Y_SEGMENT);

    glGenVertexArrays(1,&VAO);
    glBindVertexArray(VAO);

    GLuint VBO;
    glGenBuffers(1,&VBO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices) * (BALL_X_SEGMENT + 1) * (BALL_Y_SEGMENT + 1) * 3,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) * BALL_X_SEGMENT * BALL_Y_SEGMENT * 6,indices,GL_STATIC_DRAW);

    glBindVertexArray(0);//解绑
    glBindBuffer(GL_ARRAY_BUFFER,0);

    //    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();

    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;
    }

    glUseProgram(m_pShaderProgram->programId());
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES,(BALL_X_SEGMENT + 1) * (BALL_Y_SEGMENT + 1) * 3 * 6,GL_UNSIGNED_INT,0);
    glBindVertexArray(0);

    update();
}

float *GLWidget::getBallVertex(int xSegment, int ySegment)
{
    float *data = nullptr;
    data = new float[(xSegment + 1) * (ySegment + 1) * 3];

    int nIndex = 0;
    for (int y = 0; y <= ySegment; ++y) {
        for (int x = 0; x <= xSegment; ++x) {
            float xS = x * 1.0 / xSegment;
            float yS = y * 1.0 / ySegment;

            float xPos = qSin(xS * 2.0f * M_PI) * qSin(yS * M_PI);
            float yPos = qCos(yS * M_PI);
            float zPos = qCos(xS * 2.0f * M_PI) * qSin(ySegment * M_PI);

            data[nIndex] = xPos;
            data[nIndex + 1] = yPos;
            data[nIndex + 2] = zPos;

            nIndex += 3;

        }
    }

    return data;
}

int *GLWidget::getBallIndices(int xSegment, int ySegment)
{
    int *indices = nullptr;
    indices = new int[xSegment * ySegment * 6];

    int nIndex = 0;
    for (int i = 0; i < ySegment; ++i) {
        for (int j = 0; j < xSegment; ++j) {

            indices[nIndex] = i * (xSegment + 1) + j;
            indices[nIndex + 1] = (i + 1) * (xSegment + 1) + j;
            indices[nIndex + 2] = (i + 1) * (xSegment + 1) + (j + 1);
            indices[nIndex + 3] = i * (xSegment + 1) + j;
            indices[nIndex + 4] = (i + 1) * (xSegment + 1) + (j + 1);
            indices[nIndex + 5] = i * (xSegment + 1) + (j + 1);

            nIndex += 6;
        }
    }

    return indices;
}

最终效果
在这里插入图片描述

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值