1 #include "glwidget.h"
2 #include <QPainter>
3 #include <QPaintEngine>
4 #include <QOpenGLShaderProgram>
5 #include <QCoreApplication>
6 #include <qmath.h>
7 #include <QFile>
8 #ifndef GL_SRGB8_ALPHA8
9 #define GL_SRGB8_ALPHA8 0x8C43
10 #endif
11
GLWidget(const QColor & background)12 GLWidget::GLWidget( const QColor &background)
13 :
14 m_frames(0),
15 m_program1(0),
16 m_transparent(false),
17 m_background(background)
18 {
19 // setTextureFormat(GL_SRGB8_ALPHA8);
20 }
21
~GLWidget()22 GLWidget::~GLWidget()
23 {
24 // And now release all OpenGL resources.
25 makeCurrent();
26 delete m_program1;
27 delete m_vshader1;
28 delete m_fshader1;
29 m_vbo1.destroy();
30 doneCurrent();
31 }
32
paintFLLogo()33 void GLWidget::paintFLLogo()
34 {
35 m_program1->enableAttributeArray(m_vertexAttr1);
36 m_program1->enableAttributeArray(m_normalAttr1);
37
38 m_vbo1.bind();
39 // The data in the buffer is placed like this:
40 // vertex1.x, vertex1.y, vertex1.z, normal1.x, normal1.y, normal1.z, vertex2.x, ...
41 m_program1->setAttributeBuffer(m_vertexAttr1, GL_FLOAT, 0, 3, 6 * sizeof(GLfloat));
42 m_program1->setAttributeBuffer(m_normalAttr1, GL_FLOAT, 3 * sizeof(GLfloat), 3, 6 * sizeof(GLfloat));
43 m_vbo1.release();
44
45 glDrawArrays(GL_TRIANGLES, 0, m_vertices.size());
46
47 m_program1->disableAttributeArray(m_normalAttr1);
48 m_program1->disableAttributeArray(m_vertexAttr1);
49 }
50
initializeGL()51 void GLWidget::initializeGL()
52 {
53 initializeOpenGLFunctions();
54
55 m_vshader1 = new QOpenGLShader(QOpenGLShader::Vertex);
56 const char *vsrc1 =
57 "attribute highp vec4 vertex;\n"
58 "attribute mediump vec3 normal;\n"
59 "uniform mediump mat4 matrix;\n"
60 "varying mediump vec4 color;\n"
61 "void main(void)\n"
62 "{\n"
63 " vec3 toLight = normalize(vec3(0.0, 0.3, 1.0));\n"
64 " float angle = max(dot(normal, toLight), 0.0);\n"
65 " vec3 col = vec3(0.0, 0.87, 2.66);\n"
66 " color = vec4(col * 0.2 + col * 0.8 * angle, 1.0);\n"
67 " color = clamp(color, 0.0, 1.0);\n"
68 " gl_Position = matrix * vertex;\n"
69 "}\n";
70 m_vshader1->compileSourceCode(vsrc1);
71
72 m_fshader1 = new QOpenGLShader(QOpenGLShader::Fragment);
73 const char *fsrc1 =
74 "varying mediump vec4 color;\n"
75 "void main(void)\n"
76 "{\n"
77 " gl_FragColor = color;\n"
78 "}\n";
79 m_fshader1->compileSourceCode(fsrc1);
80
81 m_program1 = new QOpenGLShaderProgram;
82 m_program1->addShader(m_vshader1);
83 m_program1->addShader(m_fshader1);
84 m_program1->link();
85
86 m_vertexAttr1 = m_program1->attributeLocation("vertex");
87 m_normalAttr1 = m_program1->attributeLocation("normal");
88 m_matrixUniform1 = m_program1->uniformLocation("matrix");
89
90 m_fAngle = 0;
91 m_fScale = 1.0;
92
93 createGeometry();
94
95 // Use a vertex buffer object. Client-side pointers are old-school and should be avoided.
96 m_vbo1.create();
97 m_vbo1.bind();
98 // For the cube all the data belonging to the texture coordinates and
99 // normals is placed separately, after the vertices. Here, for the Qt logo,
100 // let's do something different and potentially more efficient: create a
101 // properly interleaved data set.
102 const int vertexCount = m_vertices.count();
103 QVector<GLfloat> buf;
104 buf.resize(vertexCount * 3 * 2);
105 GLfloat *p = buf.data();
106 for (int i = 0; i < vertexCount; ++i) {
107 *p++ = m_vertices[i].x();
108 *p++ = m_vertices[i].y();
109 *p++ = m_vertices[i].z();
110 *p++ = m_normals[i].x();
111 *p++ = m_normals[i].y();
112 *p++ = m_normals[i].z();
113 }
114 m_vbo1.allocate(buf.constData(), buf.count() * sizeof(GLfloat));
115 m_vbo1.release();
116 }
117
paintGL()118 void GLWidget::paintGL()
119 {
120 QPainter painter;
121 painter.begin(this);
122
123 painter.beginNativePainting();
124
125 glClearColor(m_background.redF(), m_background.greenF(), m_background.blueF(), m_transparent ? 0.0f : 1.0f);
126 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
127
128 glFrontFace(GL_CW);
129 glCullFace(GL_FRONT);
130 glEnable(GL_CULL_FACE);
131 glEnable(GL_DEPTH_TEST);
132
133 QMatrix4x4 modelview;
134 modelview.rotate(m_fAngle, 0.0f, 1.0f, 0.0f);
135 modelview.rotate(m_fAngle, 1.0f, 0.0f, 0.0f);
136 modelview.rotate(m_fAngle, 0.0f, 0.0f, 1.0f);
137 modelview.scale(m_fScale);
138 modelview.translate(0.0f, -0.2f, 0.0f);
139
140
141 m_program1->bind();
142 m_program1->setUniformValue(m_matrixUniform1, modelview);
143 paintFLLogo();
144 m_program1->release();
145
146 glDisable(GL_DEPTH_TEST);
147 glDisable(GL_CULL_FACE);
148
149 painter.endNativePainting();
150
151 if (const int elapsed = m_time.elapsed()) {
152 QString framesPerSecond;
153 framesPerSecond.setNum(m_frames /(elapsed / 1000.0), 'f', 2);
154 painter.setPen(Qt::blue);
155 painter.drawText(20, 40, framesPerSecond + " paintGL calls / s");
156 }
157
158 painter.end();
159
160
161 if (!(m_frames % 100)) {
162 m_time.start();
163 m_frames = 0;
164 }
165 m_fAngle += 1.0f;
166 ++m_frames;
167
168 update();
169 }
170
loadAscllStl(QString filename,qreal ratio)171 void GLWidget::loadAscllStl(QString filename, qreal ratio)
172 {
173 qDebug() << "load text file:" << filename;
174 QVector3D Normal;
175 QFile file(filename);
176 if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
177 {
178 qDebug() << "Open stl_file failed." << endl;
179 }
180 while (!file.atEnd())
181 {
182 QString line = file.readLine().trimmed();
183 QStringList words = line.split(' ', QString::SkipEmptyParts);
184 if (words[0] == "facet") {
185 Normal = QVector3D(ratio*words[2].toFloat(), ratio*words[3].toFloat(),ratio*words[4].toFloat());
186 }
187 else if (words[0] == "vertex") {
188 m_vertices << QVector3D(ratio*words[1].toFloat(), ratio*words[2].toFloat(),ratio*words[3].toFloat());
189 m_normals <<Normal;
190
191 }
192 }
193 }
194
195
createGeometry()196 void GLWidget::createGeometry()
197 {
198 m_vertices.clear();
199 m_normals.clear();
200 this->loadAscllStl(":/logo-3.STL", 0.1);
201 }
202