学习笔记3--给窗口添加一个小坐标

来源:互联网 发布:剑灵金燕捏脸数据 编辑:程序博客网 时间:2024/06/09 22:16

这次添加的内容同样是基于上一次的博文,本次打算添加两个内容:

(1) 在用光标与立方体进行交互时,改变光标的形状,让我们的界面更专业一点;

(2) 在OpenGL窗口的左下角添加一个三维直角坐标系,用来指示立方体当前的方向。

下面分别介绍两个内容的具体实现:

(1) 改变光标形状

首先,在openglwindow.h中添加私有数据成员用来管理光标:

private:    QCursor cursor;     //管理光标的显示形状

然后,在openglwindow.cpp中的构造函数中初试化在上一步中添加的数据成员:

//设置光标形状    cursor.setShape(Qt::ArrowCursor);    setCursor(cursor);
接下来,在openglwindow.h中添加光标释放事件:

    void mouseReleaseEvent(QMouseEvent *event);
接着在对鼠标事件进行更改:

void openglwindow::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 += glm::vec3(xoffset, -yoffset, 0.0f);    }}//滚轮实现对物体的放大缩小,摄像机距离远近(放大缩小)void openglwindow::wheelEvent(QWheelEvent *event){    GLfloat sensitivity = 0.0005f;    cameraPos *= (1.0f - event->delta() * sensitivity);}void openglwindow::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 openglwindow::mouseReleaseEvent(QMouseEvent *event){    //设置光标形状    cursor.setShape(Qt::ArrowCursor);    setCursor(cursor);}
(2) 添加三维坐标系

画坐标系无非就是画三条相互垂直的线。

首先,添加着色器,着色器程序,VAO,VBO等的数目(此处片段着色器与渲染立方体时相同):

const GLuint NumVertexShader = 2;       //顶点着色器的数目const GLuint NumFragmentShader = 1;     //片段着色器的数目const GLuint NumShaderProgram = 2;      //着色器程序的数目const GLuint NumVAO = 2;                //VAO的数目const GLuint NumVBO = 2;                //VBO的数目
然后,添加顶点着色器源码:

const GLchar *vertexShaderSource1 =         //绘制三维坐标        "#version 330 core\n"        "layout(location = 0) in vec3 vPosition;\n"        "layout(location = 1) in vec3 vColor;\n"        "out vec3 Color;\n"        "uniform mat4 modelCoor;\n"        "uniform mat4 viewCoor;\n"        "uniform mat4 projectionCoor;\n"        "void main()\n"        "{\n"            "Color = vColor;\n"            "gl_Position = projectionCoor * viewCoor * modelCoor * vec4(vPosition, 1.0);\n"        "}\n";
接下来,在initializeGL函数中添加编译和链接着色器程序、添加坐标轴数据、添加VAO和VBO相关信息:

/* 第二个顶点着色器 */    IDVertexShader[1] = glCreateShader(GL_VERTEX_SHADER);    glShaderSource(IDVertexShader[1], 1, &vertexShaderSource1, nullptr);    glCompileShader(IDVertexShader[1]);    //检查编译是否出错    glGetShaderiv(IDVertexShader[1], GL_COMPILE_STATUS, &success);    if (!success)    {        glGetShaderInfoLog(IDVertexShader[1], 512, NULL, infoLog);        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;    }
/* 第二个着色器程序 */    IDShaderProgram[1] = glCreateProgram();    glAttachShader(IDShaderProgram[1], IDVertexShader[1]);    glAttachShader(IDShaderProgram[1], IDFragmentShader[0]);    glLinkProgram(IDShaderProgram[1]);    //检查链接错误    glGetProgramiv(IDShaderProgram[1], GL_LINK_STATUS, &success);    if (!success) {        glGetProgramInfoLog(IDShaderProgram[1], 512, NULL, infoLog);        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;    }
//绘制坐标数据    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    };
/* 坐标 */    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);           //结束记录状态信息    /* 坐标 */
最后,在paintGL函数中绘制坐标轴:

//画坐标    glUseProgram(IDShaderProgram[1]);    glm::mat4 viewCoor;    glm::mat4 projectionCoor;    glm::mat4 modelCoor;    GLint modelCoorLoc = glGetUniformLocation(IDShaderProgram[1], "modelCoor");    GLint viewCoorLoc = glGetUniformLocation(IDShaderProgram[1], "viewCoor");    GLint projCoorLoc = glGetUniformLocation(IDShaderProgram[1], "projectionCoor");    viewCoor = glm::lookAt(cameraPos, worldCentrol, cameraUp);    projectionCoor = glm::perspective(glm::radians(45.0f), 5.0f / 3.0f, 0.1f, 100000.0f);    //modelCoor = glm::translate(modelCoor, glm::vec3(-0.38f, -0.28f, glm::length(cameraPos) - 0.8f));    modelCoor = glm::translate(modelCoor, glm::vec3(-0.48f, -0.28f, glm::length(cameraPos) - 0.8f));    modelCoor = glm::rotate(modelCoor, glm::radians(pitch), glm::vec3(1.0f, 0.0f, 0.0f));    modelCoor = glm::rotate(modelCoor, glm::radians(yaw), glm::vec3(0.0f, 1.0f, 0.0f));    glUniformMatrix4fv(viewCoorLoc, 1, GL_FALSE, glm::value_ptr(viewCoor));    glUniformMatrix4fv(projCoorLoc, 1, GL_FALSE, glm::value_ptr(projectionCoor));    glUniformMatrix4fv(modelCoorLoc, 1, GL_FALSE, glm::value_ptr(modelCoor));    glBindVertexArray(IDVAO[1]);    glDrawArrays(GL_LINES, 0, 2);    glDrawArrays(GL_LINES, 2, 2);    glDrawArrays(GL_LINES, 4, 2);    glBindVertexArray(0);
这样内容就添加完成了。

现在看一下效果:

这样,一个用来显示立方体的小程序就基本完成,当然这只是一个初级的原型,可以在这个原型的基础上添加一些功能,用来显示三维模型或者点云之类的。

编译环境及版本:Win10企业版+Qt 5.7.1(MSVC 2015, 32bit)+OpenGL3.3 Core Profile

1 0
原创粉丝点击