diff options
author | David Boddie <david.boddie@nokia.com> | 2011-04-28 17:39:11 (GMT) |
---|---|---|
committer | David Boddie <david.boddie@nokia.com> | 2011-04-28 17:39:11 (GMT) |
commit | 3abaecc3aec4e46f1c5969c33875fd45aa542385 (patch) | |
tree | 58613c5d2b765018c31d0b189e9c5a34d8adde69 /examples/opengl/cube | |
parent | ddb22795641253a026b72f752ebc769745dd41be (diff) | |
download | Qt-3abaecc3aec4e46f1c5969c33875fd45aa542385.zip Qt-3abaecc3aec4e46f1c5969c33875fd45aa542385.tar.gz Qt-3abaecc3aec4e46f1c5969c33875fd45aa542385.tar.bz2 |
Squashed commit of the changes from the mobile-examples repository
(4.7-generated-declarative branch).
Diffstat (limited to 'examples/opengl/cube')
-rw-r--r-- | examples/opengl/cube/cube.desktop | 11 | ||||
-rw-r--r-- | examples/opengl/cube/cube.png | bin | 0 -> 30341 bytes | |||
-rw-r--r-- | examples/opengl/cube/cube.pro | 40 | ||||
-rw-r--r-- | examples/opengl/cube/fshader.glsl | 18 | ||||
-rw-r--r-- | examples/opengl/cube/geometryengine.cpp | 130 | ||||
-rw-r--r-- | examples/opengl/cube/geometryengine.h | 24 | ||||
-rw-r--r-- | examples/opengl/cube/main.cpp | 22 | ||||
-rw-r--r-- | examples/opengl/cube/mainwidget.cpp | 192 | ||||
-rw-r--r-- | examples/opengl/cube/mainwidget.h | 53 | ||||
-rw-r--r-- | examples/opengl/cube/shaders.qrc | 6 | ||||
-rw-r--r-- | examples/opengl/cube/textures.qrc | 5 | ||||
-rw-r--r-- | examples/opengl/cube/vshader.glsl | 24 |
12 files changed, 525 insertions, 0 deletions
diff --git a/examples/opengl/cube/cube.desktop b/examples/opengl/cube/cube.desktop new file mode 100644 index 0000000..627e5f2 --- /dev/null +++ b/examples/opengl/cube/cube.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Version=1.0 +Type=Application +Terminal=false +Name=Cube OpenGL ES 2.0 +Exec=/opt/usr/bin/cube +Icon=cube +X-Window-Icon= +X-HildonDesk-ShowInToolbar=true +X-Osso-Type=application/x-executable diff --git a/examples/opengl/cube/cube.png b/examples/opengl/cube/cube.png Binary files differnew file mode 100644 index 0000000..42c8c51 --- /dev/null +++ b/examples/opengl/cube/cube.png diff --git a/examples/opengl/cube/cube.pro b/examples/opengl/cube/cube.pro new file mode 100644 index 0000000..64f6973 --- /dev/null +++ b/examples/opengl/cube/cube.pro @@ -0,0 +1,40 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2010-06-23T12:55:35 +# +#------------------------------------------------- + +QT += core gui + +TARGET = cube +TEMPLATE = app + +SOURCES += main.cpp + +contains(QT_CONFIG, opengl) { + message(Building with OpenGL support.) + QT += opengl + + SOURCES += mainwidget.cpp \ + geometryengine.cpp + + HEADERS += \ + mainwidget.h \ + geometryengine.h + + RESOURCES += \ + shaders.qrc \ + textures.qrc + + OTHER_FILES += \ + vshader.glsl \ + fshader.glsl +} else { + message(OpenGL support is not available.) +} + +symbian: include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) +maemo5: include($$QT_SOURCE_TREE/examples/maemo5pkgrules.pri) + +symbian: warning(This example might not fully work on Symbian platform) +simulator: warning(This example might not fully work on Simulator platform) diff --git a/examples/opengl/cube/fshader.glsl b/examples/opengl/cube/fshader.glsl new file mode 100644 index 0000000..18068cf --- /dev/null +++ b/examples/opengl/cube/fshader.glsl @@ -0,0 +1,18 @@ +#ifdef GL_ES +// Set default precision to medium +precision mediump int; +precision mediump float; +#endif + +uniform sampler2D texture; + +varying vec2 v_texcoord; + +//! [0] +void main() +{ + // Set fragment color from texture + gl_FragColor = texture2D(texture, v_texcoord); +} +//! [0] + diff --git a/examples/opengl/cube/geometryengine.cpp b/examples/opengl/cube/geometryengine.cpp new file mode 100644 index 0000000..2f6f659 --- /dev/null +++ b/examples/opengl/cube/geometryengine.cpp @@ -0,0 +1,130 @@ +#include "geometryengine.h" + +#include <QVector2D> +#include <QVector3D> + +struct VertexData +{ + QVector3D position; + QVector2D texCoord; +}; + +GeometryEngine::GeometryEngine() : vboIds(new GLuint[2]) +{ +} + +GeometryEngine::~GeometryEngine() +{ + glDeleteBuffers(2, vboIds); + delete[] vboIds; +} + +void GeometryEngine::init() +{ +//! [0] + // Generate 2 VBOs + glGenBuffers(2, vboIds); + +//! [0] + + // Initializes cube geometry and transfers it to VBOs + initCubeGeometry(); +} + +void GeometryEngine::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.0, -1.0, 1.0), QVector2D(0.0, 0.0)}, // v0 + {QVector3D( 1.0, -1.0, 1.0), QVector2D(0.33, 0.0)}, // v1 + {QVector3D(-1.0, 1.0, 1.0), QVector2D(0.0, 0.5)}, // v2 + {QVector3D( 1.0, 1.0, 1.0), QVector2D(0.33, 0.5)}, // v3 + + // Vertex data for face 1 + {QVector3D( 1.0, -1.0, 1.0), QVector2D( 0.0, 0.5)}, // v4 + {QVector3D( 1.0, -1.0, -1.0), QVector2D(0.33, 0.5)}, // v5 + {QVector3D( 1.0, 1.0, 1.0), QVector2D(0.0, 1.0)}, // v6 + {QVector3D( 1.0, 1.0, -1.0), QVector2D(0.33, 1.0)}, // v7 + + // Vertex data for face 2 + {QVector3D( 1.0, -1.0, -1.0), QVector2D(0.66, 0.5)}, // v8 + {QVector3D(-1.0, -1.0, -1.0), QVector2D(1.0, 0.5)}, // v9 + {QVector3D( 1.0, 1.0, -1.0), QVector2D(0.66, 1.0)}, // v10 + {QVector3D(-1.0, 1.0, -1.0), QVector2D(1.0, 1.0)}, // v11 + + // Vertex data for face 3 + {QVector3D(-1.0, -1.0, -1.0), QVector2D(0.66, 0.0)}, // v12 + {QVector3D(-1.0, -1.0, 1.0), QVector2D(1.0, 0.0)}, // v13 + {QVector3D(-1.0, 1.0, -1.0), QVector2D(0.66, 0.5)}, // v14 + {QVector3D(-1.0, 1.0, 1.0), QVector2D(1.0, 0.5)}, // v15 + + // Vertex data for face 4 + {QVector3D(-1.0, -1.0, -1.0), QVector2D(0.33, 0.0)}, // v16 + {QVector3D( 1.0, -1.0, -1.0), QVector2D(0.66, 0.0)}, // v17 + {QVector3D(-1.0, -1.0, 1.0), QVector2D(0.33, 0.5)}, // v18 + {QVector3D( 1.0, -1.0, 1.0), QVector2D(0.66, 0.5)}, // v19 + + // Vertex data for face 5 + {QVector3D(-1.0, 1.0, 1.0), QVector2D(0.33, 0.5)}, // v20 + {QVector3D( 1.0, 1.0, 1.0), QVector2D(0.66, 0.5)}, // v21 + {QVector3D(-1.0, 1.0, -1.0), QVector2D(0.33, 1.0)}, // v22 + {QVector3D( 1.0, 1.0, -1.0), QVector2D(0.66, 1.0)} // 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) + }; + +//! [1] + // Transfer vertex data to VBO 0 + glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]); + glBufferData(GL_ARRAY_BUFFER, 24 * sizeof(VertexData), vertices, GL_STATIC_DRAW); + + // Transfer index data to VBO 1 + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[1]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 34 * sizeof(GLushort), indices, GL_STATIC_DRAW); +//! [1] +} + +//! [2] +void GeometryEngine::drawCubeGeometry(QGLShaderProgram *program) +{ + // Tell OpenGL which VBOs to use + glBindBuffer(GL_ARRAY_BUFFER, vboIds[0]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIds[1]); + + // Offset for position + int offset = 0; + + // Tell OpenGL programmable pipeline how to locate vertex position data + int vertexLocation = program->attributeLocation("a_position"); + program->enableAttributeArray(vertexLocation); + glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void *)offset); + + // 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); + glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void *)offset); + + // Draw cube geometry using indices from VBO 1 + glDrawElements(GL_TRIANGLE_STRIP, 34, GL_UNSIGNED_SHORT, 0); +} +//! [2] diff --git a/examples/opengl/cube/geometryengine.h b/examples/opengl/cube/geometryengine.h new file mode 100644 index 0000000..d0fba69 --- /dev/null +++ b/examples/opengl/cube/geometryengine.h @@ -0,0 +1,24 @@ +#ifndef GEOMETRYENGINE_H +#define GEOMETRYENGINE_H + +#include <QtOpenGL/QGLFunctions> +#include <QtOpenGL/QGLShaderProgram> + +class GeometryEngine : protected QGLFunctions +{ +public: + GeometryEngine(); + virtual ~GeometryEngine(); + + void init(); + + void drawCubeGeometry(QGLShaderProgram *program); + +private: + void initCubeGeometry(); + + GLuint *vboIds; + +}; + +#endif // GEOMETRYENGINE_H diff --git a/examples/opengl/cube/main.cpp b/examples/opengl/cube/main.cpp new file mode 100644 index 0000000..faac8a0 --- /dev/null +++ b/examples/opengl/cube/main.cpp @@ -0,0 +1,22 @@ +#include <QtGui/QApplication> +#include <QLabel> + +#ifndef QT_NO_OPENGL +#include "mainwidget.h" +#endif + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + a.setApplicationName("cube"); + a.setApplicationVersion("0.1"); +#ifndef QT_NO_OPENGL + MainWidget w; + w.resize(640, 480); + w.show(); +#else + QLabel * notifyLabel = new QLabel("OpenGL Support required"); + notifyLabel->show(); +#endif + return a.exec(); +} diff --git a/examples/opengl/cube/mainwidget.cpp b/examples/opengl/cube/mainwidget.cpp new file mode 100644 index 0000000..bead5f79 --- /dev/null +++ b/examples/opengl/cube/mainwidget.cpp @@ -0,0 +1,192 @@ +#include "mainwidget.h" + +#include "geometryengine.h" + +#include <QtOpenGL/QGLShaderProgram> + +#include <QBasicTimer> +#include <QMouseEvent> + +#include <math.h> + +#include <QDebug> + +MainWidget::MainWidget(QWidget *parent) : + QGLWidget(parent), + timer(new QBasicTimer), + program(new QGLShaderProgram), + geometries(new GeometryEngine) +{ +} + +MainWidget::~MainWidget() +{ + delete timer; timer = 0; + delete program; program = 0; + delete geometries; geometries = 0; + + deleteTexture(texture); +} + +//! [0] +void MainWidget::mousePressEvent(QMouseEvent *e) +{ + // Saving mouse press position + mousePressPosition = QVector2D(e->posF()); +} + +void MainWidget::mouseReleaseEvent(QMouseEvent *e) +{ + // Mouse release position - mouse press position + QVector2D diff = QVector2D(e->posF()) - mousePressPosition; + + // Rotation axis is perpendicular to the mouse position difference + // vector + QVector3D n = QVector3D(diff.y(), diff.x(), 0.0).normalized(); + + // Accelerate angular speed relative to the length of the mouse sweep + qreal acc = diff.length() / 100.0; + + // Calculate new rotation axis as weighted sum + rotationAxis = (rotationAxis * angularSpeed + n * acc).normalized(); + + // Increase angular speed + angularSpeed += acc; +} +//! [0] + +//! [1] +void MainWidget::timerEvent(QTimerEvent *e) +{ + Q_UNUSED(e); + + // Decrease angular speed (friction) + angularSpeed *= 0.99; + + // Stop rotation when speed goes below threshold + if (angularSpeed < 0.01) + angularSpeed = 0.0; + else { + // Update rotation + rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angularSpeed) * rotation; + + // Update scene + updateGL(); + } +} +//! [1] + +void MainWidget::initializeGL() +{ + qglClearColor(Qt::black); + + qDebug() << "Initializing shaders..."; + initShaders(); + + qDebug() << "Initializing textures..."; + initTextures(); + +//! [2] + // Enable depth buffer + glEnable(GL_DEPTH_TEST); + + // Enable back face culling + glEnable(GL_CULL_FACE); +//! [2] + + qDebug() << "Initializing geometries..."; + geometries->init(); + + // using QBasicTimer because its faster that QTimer + timer->start(12, this); +} + +//! [3] +void MainWidget::initShaders() +{ + // Overriding system locale until shaders are compiled + setlocale(LC_NUMERIC, "C"); + + // Compiling vertex shader + if (!program->addShaderFromSourceFile(QGLShader::Vertex, ":/vshader.glsl")) + close(); + + // Compiling fragment shader + if (!program->addShaderFromSourceFile(QGLShader::Fragment, ":/fshader.glsl")) + close(); + + // Linking shader pipeline + if (!program->link()) + close(); + + // Binding shader pipeline for use + if (!program->bind()) + close(); + + // Restore system locale + setlocale(LC_ALL, ""); +} +//! [3] + +//! [4] +void MainWidget::initTextures() +{ + // Loading cube.png to texture unit 0 + glActiveTexture(GL_TEXTURE0); + glEnable(GL_TEXTURE_2D); + texture = bindTexture(QImage(":/cube.png")); + + // Set nearest filtering mode for texture minification + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + // Set bilinear filtering mode for texture magnification + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Wrap texture coordinates by repeating + // f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); +} +//! [4] + +//! [5] +void MainWidget::resizeGL(int w, int h) +{ + // Set OpenGL viewport to cover whole widget + glViewport(0, 0, w, 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); +} +//! [5] + +void MainWidget::paintGL() +{ + // Clear color and depth buffer + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + +//! [6] + // Calculate model view transformation + QMatrix4x4 matrix; + matrix.translate(0.0, 0.0, -5.0); + matrix.rotate(rotation); + + // Set modelview-projection matrix + program->setUniformValue("mvp_matrix", projection * matrix); +//! [6] + + // Using texture unit 0 which contains cube.png + program->setUniformValue("texture", 0); + + // Draw cube geometry + geometries->drawCubeGeometry(program); +} diff --git a/examples/opengl/cube/mainwidget.h b/examples/opengl/cube/mainwidget.h new file mode 100644 index 0000000..595173b --- /dev/null +++ b/examples/opengl/cube/mainwidget.h @@ -0,0 +1,53 @@ +#ifndef MAINWIDGET_H +#define MAINWIDGET_H + +#include <QtOpenGL/QGLWidget> + +#include <QMatrix4x4> +#include <QQuaternion> +#include <QVector2D> + +class QBasicTimer; +class QGLShaderProgram; + +class GeometryEngine; + +class MainWidget : public QGLWidget +{ + Q_OBJECT +public: + explicit MainWidget(QWidget *parent = 0); + virtual ~MainWidget(); + +signals: + +public slots: + +protected: + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + void timerEvent(QTimerEvent *e); + + void initializeGL(); + void resizeGL(int w, int h); + void paintGL(); + + void initShaders(); + void initTextures(); + +private: + QBasicTimer *timer; + QGLShaderProgram *program; + GeometryEngine *geometries; + + GLuint texture; + + QMatrix4x4 projection; + + QVector2D mousePressPosition; + QVector3D rotationAxis; + qreal angularSpeed; + QQuaternion rotation; +}; + +#endif // MAINWIDGET_H diff --git a/examples/opengl/cube/shaders.qrc b/examples/opengl/cube/shaders.qrc new file mode 100644 index 0000000..bfc4b25 --- /dev/null +++ b/examples/opengl/cube/shaders.qrc @@ -0,0 +1,6 @@ +<RCC> + <qresource prefix="/"> + <file>vshader.glsl</file> + <file>fshader.glsl</file> + </qresource> +</RCC> diff --git a/examples/opengl/cube/textures.qrc b/examples/opengl/cube/textures.qrc new file mode 100644 index 0000000..fe53be5 --- /dev/null +++ b/examples/opengl/cube/textures.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>cube.png</file> + </qresource> +</RCC> diff --git a/examples/opengl/cube/vshader.glsl b/examples/opengl/cube/vshader.glsl new file mode 100644 index 0000000..cfdc061 --- /dev/null +++ b/examples/opengl/cube/vshader.glsl @@ -0,0 +1,24 @@ +#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; + +//! [0] +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; +} +//! [0] |