From 69dfbe669396174a993f759f485a28fa8131e387 Mon Sep 17 00:00:00 2001 From: kazu Date: Fri, 15 Jul 2016 16:39:38 +0200 Subject: [PATCH] worked on OpenGL ES --- main.cpp | 26 ++++++--- map/Geometry.cpp | 124 ++++++++++++++++++++++++++++++++++++++++++ map/Geometry.h | 23 ++++++++ map/MapView.cpp | 119 ++++++++++++++++++++++++++++------------ map/MapView.h | 19 ++++++- misc/fixc11.h | 4 ++ qml.qrc | 5 +- res/gl/fragment1.glsl | 16 ++++++ res/gl/vertex1.glsl | 22 ++++++++ yasmin.pro | 14 +++-- 10 files changed, 319 insertions(+), 53 deletions(-) create mode 100644 map/Geometry.cpp create mode 100644 map/Geometry.h create mode 100644 res/gl/fragment1.glsl create mode 100644 res/gl/vertex1.glsl diff --git a/main.cpp b/main.cpp index b8529af..c45c2a8 100644 --- a/main.cpp +++ b/main.cpp @@ -46,22 +46,30 @@ int main(int argc, char *argv[]) { // std::this_thread::sleep_for(std::chrono::seconds(10000)); + + + //QGuiApplication app(argc, argv); QApplication app(argc, argv); - QMainWindow* win = new QMainWindow(); + // OpenGL Setup + QSurfaceFormat format; + format.setDepthBufferSize(24); + QSurfaceFormat::setDefaultFormat(format); - QVBoxLayout* lay = new QVBoxLayout(); - win->setLayout(lay); +// QMainWindow* win = new QMainWindow(); - MapView* map = new MapView(win); - lay->addWidget(map); +// QVBoxLayout* lay = new QVBoxLayout(); +// win->setLayout(lay); + + MapView* map = new MapView(); +// lay->addWidget(map); map->setMinimumHeight(200); map->setMinimumWidth(200); - - win->setMinimumWidth(400); - win->setMinimumHeight(400); - win->show(); + map->show(); +// win->setMinimumWidth(400); +// win->setMinimumHeight(400); +// win->show(); // QQmlApplicationEngine engine; // engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); diff --git a/map/Geometry.cpp b/map/Geometry.cpp new file mode 100644 index 0000000..76c54cd --- /dev/null +++ b/map/Geometry.cpp @@ -0,0 +1,124 @@ +#include "Geometry.h" + +#include +#include + +struct VertexData +{ + QVector3D position; + QVector2D texCoord; +}; + +Geometry::Geometry() : indexBuf(QOpenGLBuffer::IndexBuffer) { + + initializeOpenGLFunctions(); + + // Generate 2 VBOs + arrayBuf.create(); + indexBuf.create(); + + // Initializes cube geometry and transfers it to VBOs + initCubeGeometry(); + +} + +Geometry::~Geometry() { + arrayBuf.destroy(); + indexBuf.destroy(); +} + +void Geometry::initCubeGeometry() { + + // For cube we would need only 8 vertices but we have to + // duplicate vertex for each face because texture coordinate + // is different. + VertexData vertices[] = { + // Vertex data for face 0 + {QVector3D(-1.0f, -1.0f, 1.0f), QVector2D(0.0f, 0.0f)}, // v0 + {QVector3D( 1.0f, -1.0f, 1.0f), QVector2D(0.33f, 0.0f)}, // v1 + {QVector3D(-1.0f, 1.0f, 1.0f), QVector2D(0.0f, 0.5f)}, // v2 + {QVector3D( 1.0f, 1.0f, 1.0f), QVector2D(0.33f, 0.5f)}, // v3 + + // Vertex data for face 1 + {QVector3D( 1.0f, -1.0f, 1.0f), QVector2D( 0.0f, 0.5f)}, // v4 + {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.33f, 0.5f)}, // v5 + {QVector3D( 1.0f, 1.0f, 1.0f), QVector2D(0.0f, 1.0f)}, // v6 + {QVector3D( 1.0f, 1.0f, -1.0f), QVector2D(0.33f, 1.0f)}, // v7 + + // Vertex data for face 2 + {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.5f)}, // v8 + {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(1.0f, 0.5f)}, // v9 + {QVector3D( 1.0f, 1.0f, -1.0f), QVector2D(0.66f, 1.0f)}, // v10 + {QVector3D(-1.0f, 1.0f, -1.0f), QVector2D(1.0f, 1.0f)}, // v11 + + // Vertex data for face 3 + {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.0f)}, // v12 + {QVector3D(-1.0f, -1.0f, 1.0f), QVector2D(1.0f, 0.0f)}, // v13 + {QVector3D(-1.0f, 1.0f, -1.0f), QVector2D(0.66f, 0.5f)}, // v14 + {QVector3D(-1.0f, 1.0f, 1.0f), QVector2D(1.0f, 0.5f)}, // v15 + + // Vertex data for face 4 + {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(0.33f, 0.0f)}, // v16 + {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.0f)}, // v17 + {QVector3D(-1.0f, -1.0f, 1.0f), QVector2D(0.33f, 0.5f)}, // v18 + {QVector3D( 1.0f, -1.0f, 1.0f), QVector2D(0.66f, 0.5f)}, // v19 + + // Vertex data for face 5 + {QVector3D(-1.0f, 1.0f, 1.0f), QVector2D(0.33f, 0.5f)}, // v20 + {QVector3D( 1.0f, 1.0f, 1.0f), QVector2D(0.66f, 0.5f)}, // v21 + {QVector3D(-1.0f, 1.0f, -1.0f), QVector2D(0.33f, 1.0f)}, // v22 + {QVector3D( 1.0f, 1.0f, -1.0f), QVector2D(0.66f, 1.0f)} // v23 + }; + + // Indices for drawing cube faces using triangle strips. + // Triangle strips can be connected by duplicating indices + // between the strips. If connecting strips have opposite + // vertex order then last index of the first strip and first + // index of the second strip needs to be duplicated. If + // connecting strips have same vertex order then only last + // index of the first strip needs to be duplicated. + GLushort indices[] = { + 0, 1, 2, 3, 3, // Face 0 - triangle strip ( v0, v1, v2, v3) + 4, 4, 5, 6, 7, 7, // Face 1 - triangle strip ( v4, v5, v6, v7) + 8, 8, 9, 10, 11, 11, // Face 2 - triangle strip ( v8, v9, v10, v11) + 12, 12, 13, 14, 15, 15, // Face 3 - triangle strip (v12, v13, v14, v15) + 16, 16, 17, 18, 19, 19, // Face 4 - triangle strip (v16, v17, v18, v19) + 20, 20, 21, 22, 23 // Face 5 - triangle strip (v20, v21, v22, v23) + }; + + // Transfer vertex data to VBO 0 + arrayBuf.bind(); + arrayBuf.allocate(vertices, 24 * sizeof(VertexData)); + + // Transfer index data to VBO 1 + indexBuf.bind(); + indexBuf.allocate(indices, 34 * sizeof(GLushort)); + +} + +void Geometry::drawCubeGeometry(QOpenGLShaderProgram *program) { + + // Tell OpenGL which VBOs to use + arrayBuf.bind(); + indexBuf.bind(); + + // Offset for position + quintptr offset = 0; + + // Tell OpenGL programmable pipeline how to locate vertex position data + int vertexLocation = program->attributeLocation("a_position"); + program->enableAttributeArray(vertexLocation); + program->setAttributeBuffer(vertexLocation, GL_FLOAT, offset, 3, sizeof(VertexData)); + + // Offset for texture coordinate + offset += sizeof(QVector3D); + + // Tell OpenGL programmable pipeline how to locate vertex texture coordinate data + int texcoordLocation = program->attributeLocation("a_texcoord"); + program->enableAttributeArray(texcoordLocation); + program->setAttributeBuffer(texcoordLocation, GL_FLOAT, offset, 2, sizeof(VertexData)); + + // Draw cube geometry using indices from VBO 1 + glDrawElements(GL_TRIANGLE_STRIP, 34, GL_UNSIGNED_SHORT, 0); + +} diff --git a/map/Geometry.h b/map/Geometry.h new file mode 100644 index 0000000..216a775 --- /dev/null +++ b/map/Geometry.h @@ -0,0 +1,23 @@ +#ifndef GEOMETRY_H +#define GEOMETRY_H + +#include +#include +#include + +class Geometry : protected QOpenGLFunctions +{ +public: + Geometry(); + virtual ~Geometry(); + + void drawCubeGeometry(QOpenGLShaderProgram *program); + +private: + void initCubeGeometry(); + + QOpenGLBuffer arrayBuf; + QOpenGLBuffer indexBuf; +}; + +#endif // GEOMETRY_H diff --git a/map/MapView.cpp b/map/MapView.cpp index d7c9b39..0656384 100644 --- a/map/MapView.cpp +++ b/map/MapView.cpp @@ -1,53 +1,100 @@ #include "MapView.h" +#include +#include "Geometry.h" + +// http://doc.qt.io/qt-5/qtopengl-cube-example.html + +MapView::MapView(QWidget* parent) : QOpenGLWidget(parent) { -MapView::MapView(QWidget* parent) : QGLWidget(parent) { }; - void MapView::initializeGL() { +void MapView::timerEvent(QTimerEvent *) { + update(); +} - qglClearColor(Qt::black); +void MapView::initializeGL() { - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - //glShadeModel(GL_SMOOTH); - //glEnable(GL_LIGHTING); - //glEnable(GL_LIGHT0); + //qglClearColor(Qt::black); - //static GLfloat lightPosition[4] = { 0, 0, 10, 1.0 }; - //glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); + //glEnable(GL_DEPTH_TEST); + //glEnable(GL_CULL_FACE); + //glShadeModel(GL_SMOOTH); + //glEnable(GL_LIGHTING); + //glEnable(GL_LIGHT0); - } + //static GLfloat lightPosition[4] = { 0, 0, 10, 1.0 }; + //glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); - void MapView::paintGL() { + initializeOpenGLFunctions(); + + geo = new Geometry(); + + if (!program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/res/gl/vertex1.glsl")) {throw "1";} + if (!program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/res/gl/fragment1.glsl")) {throw "2";} + if (!program.link()) {throw "3";} + if (!program.bind()) {throw "4";} + + timer.start(60, this); + +} + +void MapView::paintGL() { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + //glLoadIdentity(); + //glTranslatef(0.0, 0.0, -10.0); + //glRotatef(20 / 16.0, 1.0, 0.0, 0.0); + //glRotatef(30 / 16.0, 0.0, 1.0, 0.0); + //glRotatef(60 / 16.0, 0.0, 0.0, 1.0); + draw(); +} + +void MapView::resizeGL(int w, int h) { + + // Calculate aspect ratio + qreal aspect = qreal(w) / qreal(h ? h : 1); + + // Set near plane to 3.0, far plane to 7.0, field of view 45 degrees + const qreal zNear = 3.0, zFar = 7.0, fov = 45.0; + + // Reset projection + projection.setToIdentity(); + + // Set perspective projection + projection.perspective(fov, aspect, zNear, zFar); + +} + +void MapView::draw() { + + + static float angularSpeed = 0; + angularSpeed += 0.5; + + // Clear color and depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - //glLoadIdentity(); - //glTranslatef(0.0, 0.0, -10.0); - //glRotatef(20 / 16.0, 1.0, 0.0, 0.0); - //glRotatef(30 / 16.0, 0.0, 1.0, 0.0); - //glRotatef(60 / 16.0, 0.0, 0.0, 1.0); - draw(); - } - void MapView::resizeGL(int width, int height) { - int side = qMin(width, height); - glViewport((width - side) / 2, (height - side) / 2, side, side); + //texture->bind(); + QVector3D rotationAxis(1,1,1); + QQuaternion rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angularSpeed); - //glMatrixMode(GL_PROJECTION); - //glLoadIdentity(); - #ifdef QT_OPENGL_ES_1 - glOrthof(-2, +2, -2, +2, 1.0, 15.0); - #else - //glOrtho(-2, +2, -2, +2, 1.0, 15.0); - #endif - //glMatrixMode(GL_MODELVIEW); - } + // Calculate model view transformation + QMatrix4x4 matrix; + matrix.translate(0.0, 0.0, -5.0); + matrix.rotate(rotation); - void MapView::draw() - { - qglColor(Qt::red); - /*glBegin(GL_QUADS); + // Set modelview-projection matrix + program.setUniformValue("mvp_matrix", projection * matrix); + + // Use texture unit 0 which contains cube.png + program.setUniformValue("texture", 0); + + // Draw cube geometry + geo->drawCubeGeometry(&program); + + //qglColor(Qt::red); + /*glBegin(GL_QUADS); glNormal3f(0,0,-1); glVertex3f(-1,-1,0); glVertex3f(-1,1,0); @@ -79,4 +126,4 @@ MapView::MapView(QWidget* parent) : QGLWidget(parent) { glVertex3f(-1,-1,0); glVertex3f(0,0,1.2); glEnd();*/ - } +} diff --git a/map/MapView.h b/map/MapView.h index 2790bb9..f33ad47 100644 --- a/map/MapView.h +++ b/map/MapView.h @@ -1,9 +1,22 @@ #ifndef MAPVIEW_H #define MAPVIEW_H -#include +#include +#include +#include +#include -class MapView : public QGLWidget { +class Geometry; + +class MapView : public QOpenGLWidget, protected QOpenGLFunctions { + +private: + + QMatrix4x4 projection; + QOpenGLShaderProgram program; + Geometry* geo; + + QBasicTimer timer; public: @@ -11,6 +24,8 @@ public: protected: + void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE; + void initializeGL(); void paintGL(); diff --git a/misc/fixc11.h b/misc/fixc11.h index 28101b4..9c6b36a 100644 --- a/misc/fixc11.h +++ b/misc/fixc11.h @@ -1,6 +1,8 @@ #ifndef FIXC11_H #define FIXC11_H +#ifdef ANDROID + #include #include @@ -47,4 +49,6 @@ namespace std { } +#endif + #endif // FIXC11_H diff --git a/qml.qrc b/qml.qrc index 4d8ed66..12aec8d 100644 --- a/qml.qrc +++ b/qml.qrc @@ -1,3 +1,6 @@ - + + res/gl/fragment1.glsl + res/gl/vertex1.glsl + diff --git a/res/gl/fragment1.glsl b/res/gl/fragment1.glsl new file mode 100644 index 0000000..73d9263 --- /dev/null +++ b/res/gl/fragment1.glsl @@ -0,0 +1,16 @@ +#ifdef GL_ES +// Set default precision to medium +precision mediump int; +precision mediump float; +#endif + +uniform sampler2D texture; + +varying vec2 v_texcoord; + +void main() +{ + // Set fragment color from texture + gl_FragColor = texture2D(texture, v_texcoord); + gl_FragColor = vec4(1,1,1,1); +} diff --git a/res/gl/vertex1.glsl b/res/gl/vertex1.glsl new file mode 100644 index 0000000..5fa4678 --- /dev/null +++ b/res/gl/vertex1.glsl @@ -0,0 +1,22 @@ +#ifdef GL_ES +// Set default precision to medium +precision mediump int; +precision mediump float; +#endif + +uniform mat4 mvp_matrix; + +attribute vec4 a_position; +attribute vec2 a_texcoord; + +varying vec2 v_texcoord; + +void main() +{ + // Calculate vertex position in screen space + gl_Position = mvp_matrix * a_position; + + // Pass texture coordinate to fragment shader + // Value will be automatically interpolated to fragments inside polygon faces + v_texcoord = a_texcoord; +} diff --git a/yasmin.pro b/yasmin.pro index 3d2b3ec..e7db070 100644 --- a/yasmin.pro +++ b/yasmin.pro @@ -3,8 +3,8 @@ TEMPLATE = app QT += qml opengl # android? -QT += androidextras sensors -DEFINES += ANDROID +#QT += androidextras sensors +#DEFINES += ANDROID CONFIG += c++11 @@ -21,7 +21,8 @@ OTHER_FILES += \ SOURCES += \ main.cpp \ - map/MapView.cpp + map/MapView.cpp \ + map/Geometry.cpp RESOURCES += qml.qrc @@ -51,7 +52,10 @@ HEADERS += \ misc/Debug.h \ misc/fixc11.h \ sensors/dummy/WiFiSensorDummy.h \ - map/MapView.h + map/MapView.h \ + map/Geometry.h DISTFILES += \ - android-sources/src/MyActivity.java + android-sources/src/MyActivity.java \ + res/gl/vertex1.glsl \ + res/gl/fragment1.glsl