xref: /OK3568_Linux_fs/app/forlinx/flapp/src/plugins/opengl/glwidget.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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