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