此项目为“OpenGL画坐标系1”的拓展,1的链接:https://blog.csdn.net/qq_37996632/article/details/103149535
思路:在原有的直线坐标轴上加上一个小的四棱锥,当然圆锥也可以,不过绘制圆锥的难度要大一点。
整体效果如下:
项目整体目录如下:
注意:对比“OpenGL画坐标系1”,修改了Coordinate.h,Coordinate.cpp,Widget.cpp三个文件,并且删除了y轴和z轴的着色器文件,整合到一个着色器文件里。
Coordinate.h
#ifndef COORDINATE_H
#define COORDINATE_H
#include <QOpenGLExtraFunctions>
class Coordinate : protected QOpenGLExtraFunctions
{
public:
Coordinate();
~Coordinate();
void init();
void drawCoordAxis(GLuint lineVBO, GLfloat *lineVertices, GLuint pyramidVBO, GLfloat *pyramidVertices);
void drawX();
void drawY();
void drawZ();
private:
GLuint linesVBO[3]; // VBO of lines
GLuint pyramidsVBO[3]; // VBO of pyramids
};
#endif // COORDINATE_H
Coordinate.cpp
#include "coordinate.h"
#define VNAME(value) (#value)
#include <QDebug>
// vertices of lines
GLfloat lineXVertices[6] = {
0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f
};
GLfloat lineYVertices[] = {
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f
};
GLfloat lineZVertices[] = {
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
// vertices of pyramids
GLfloat pyramidXVertices[] =
{
1.0f, 0.01f, 0.01f, // x1
1.0f, 0.01f, -0.01f, // x2
1.0f, -0.01f, -0.01f, // x3
1.0f, 0.01f, 0.01f, // x1
1.0f, -0.01f, -0.01f, // x3
1.0f, -0.01f, 0.01f, // x4
1.1f, 0.0f, 0.0f, // 0
1.0f, 0.01f, 0.01f, // x1
1.0f, -0.01f, 0.01f, // x4
1.1f, 0.0f, 0.0f, // 0
1.0f, 0.01f, 0.01f, // x1
1.0f, 0.01f, -0.01f, // x2
1.1f, 0.0f, 0.0f, // 0
1.0f, 0.01f, -0.01f, // x2
1.0f, -0.01f, -0.01f, // x3
1.1f, 0.0f, 0.0f, // 0
1.0f, -0.01f, -0.01f, // x3
1.0f, -0.01f, 0.01f // x4
};
GLfloat pyramidYVertices[] =
{
0.01f, 1.0f, -0.01f, // x1
-0.01f, 1.0f, -0.01f, // x2
-0.01f, 1.0f, 0.01f, // x3
0.01f, 1.0f, -0.01f, // x1
-0.01f, 1.0f, 0.01f, // x3
0.01f, 1.0f, 0.01f, // x4
0.0f, 1.1f, 0.0f, // 0
0.01f, 1.0f, -0.01f, // x1
0.01f, 1.0f, 0.01f, // x4
0.0f, 1.1f, 0.0f, // 0
0.01f, 1.0f, -0.01f, // x1
-0.01f, 1.0f, -0.01f, // x2
0.0f, 1.1f, 0.0f, // 0
-0.01f, 1.0f, -0.01f, // x2
-0.01f, 1.0f, 0.01f, // x3
0.0f, 1.1f, 0.0f, // 0
-0.01f, 1.0f, 0.01f, // x3
0.01f, 1.0f, 0.01f // x4
};
GLfloat pyramidZVertices[] =
{
0.01f, 0.01f, 1.0f, // x1
-0.01f, 0.01f, 1.0f, // x2
-0.01f, -0.01f, 1.0f, // x3
0.01f, 0.01f, 1.0f, // x1
-0.01f, -0.01f, 1.0f, // x3
0.01f, -0.01f, 1.0f, // x4
0.0f, 0.0f, 1.1f, // 0
0.01f, 0.01f, 1.0f, // x1
0.01f, -0.01f, 1.0f, // x4
0.0f, 0.0f, 1.1f, // 0
0.01f, 0.01f, 1.0f, // x1
-0.01f, 0.01f, 1.0f, // x2
0.0f, 0.0f, 1.1f, // 0
-0.01f, 0.01f, 1.0f, // x2
-0.01f, -0.01f, 1.0f, // x3
0.0f, 0.0f, 1.1f, // 0
-0.01f, -0.01f, 1.0f, // x3
0.01f, -0.01f, 1.0f // x4
};
Coordinate::Coordinate()
{
this->initializeOpenGLFunctions();
}
Coordinate::~Coordinate()
{
glDeleteBuffers(3, linesVBO);
glDeleteBuffers(3, pyramidsVBO);
}
void Coordinate::init()
{
// generate VBO
glGenBuffers(3, linesVBO);
glGenBuffers(3, pyramidsVBO);
}
void Coordinate::drawCoordAxis(GLuint lineVBO, GLfloat *lineVertices, GLuint pyramidVBO, GLfloat *pyramidVertices)
{
// line
glBindBuffer(GL_ARRAY_BUFFER, lineVBO);
// 24为sizeof(lineVertices)的大小,因数组作为参数传递,sizeof()后值为1
glBufferData(GL_ARRAY_BUFFER, 24, lineVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_LINES, 0, 2);
// pyramid
glBindBuffer(GL_ARRAY_BUFFER, pyramidVBO);
glBufferData(GL_ARRAY_BUFFER, 216, pyramidVertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 18);
}
void Coordinate::drawX()
{
drawCoordAxis(linesVBO[0], lineXVertices, pyramidsVBO[0], pyramidXVertices);
}
void Coordinate::drawY()
{
drawCoordAxis(linesVBO[1], lineYVertices, pyramidsVBO[1], pyramidYVertices);
}
void Coordinate::drawZ()
{
drawCoordAxis(linesVBO[2], lineZVertices, pyramidsVBO[2], pyramidZVertices);
}
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <coordinate.h>
#include <shader.h>
class Widget : public QOpenGLWidget, protected QOpenGLExtraFunctions
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
protected:
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
private:
Coordinate *coordinate;
Shader *shader;
GLuint axisIndex;
};
#endif // WIDGET_H
Widget. cpp
#include "widget.h"
Widget::Widget(QWidget *parent) : QOpenGLWidget(parent)
{
this->setWindowTitle("Coordinate");
}
Widget::~Widget()
{
delete shader;
}
void Widget::initializeGL(){
this->initializeOpenGLFunctions();
// load shaders
shader = new Shader(":/shaders/Coordinate.vert",":/shaders/Coordinate.frag");
coordinate = new Coordinate();
coordinate->init();
// set projection and view matrix
QMatrix4x4 projection, view;
view.translate(QVector3D(0.0f, -0.5f, -3.0f)); // camera view
projection.perspective(45.0f, (GLfloat)width() / (GLfloat)height(), 0.1f, 100.0f);
shader->use();
shader->setMatrix4f("view", view);
shader->setMatrix4f("projection", projection);
glEnable(GL_DEPTH_TEST);
}
void Widget::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}
void Widget::paintGL()
{
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 model;
model.setToIdentity(); // initializing, Set the rectangle to an identity matrix
model.rotate(-45.0f, 0.0f, 1.0f ,0.0f); // rotate coordinate system to aovid blocking z-axis
// draw x,y,z coordinate axis
shader->use();
shader->setMatrix4f("model", model);
shader->setBool("axisIndex", 1);
coordinate->drawX();
shader->setBool("axisIndex", 2);
coordinate->drawY();
shader->setBool("axisIndex", 3);
coordinate->drawZ();
}
Coordinate.vert
#version 330 core
layout (location = 0) in vec3 aPos;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main(){
gl_Position = projection * view * model * vec4(aPos, 1.0f);
}
Coordinate.frag
#version 330 core
out vec4 FragColor;
uniform int axisIndex;
void main()
{
if(axisIndex == 1)
{
FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
}
else if(axisIndex == 2)
{
FragColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);
}
else if(axisIndex == 3)
{
FragColor = vec4(0.0f, 0.0f, 1.0f, 1.0f);
}
}