Posts RSS Comments RSS Del.icio.us Digg Technorati Blinklist Furl reddit 65 Posts and Comments till now
This wordpress theme is downloaded from wordpress themes website.

Archive for the 'Qt OpenGL' Category

Qt OpenGL model viewer (STL)

My previous post contains notes for some reading I did to learn about Qt’s OpenGL support.  The post before that mentions integrating Open Asset Import Library (assimp) into my OpenGL SDL project.  Continuing on both themes, I wrote (from scratch) a simple STL model viewer with Qt (when I wrote this post, I used Qt Creator 3.2.0 with Qt 5.3.1).  Uses modern OpenGL (no legacy fixed function).  Uses Qt’s OpenGL classes layer when available.  Otherwise, it uses standard OpenGL.

Features include:
* load STL models and lays them out in a row with bounding box based spacing
* mouse left rotate model, mouse right translate camera, mouse wheel zoom camera, WASD rotates orbital camera (spherical coordinates)
* basic Phong lighting
* use per-face normals in STL file, or generate per-face normals, or generate per-vertex normals
* uniform scales each model within bounding box range 15x15x15 to 25x25x25
* calculate surface area, calculate volume

image image image

For this project, I originally thought of Qt as mostly an alternative to SDL – it gives an OpenGL context and user input (mouse, keyboard).  However, Qt also focuses on cross-platform GUI support, and on classes that are an alternative to C++ standard library (eg QString, QVector, QHash, QFile).  Qt has helper functions related to 3D math (QVector3D, QMatrix4x4) that integrate well with Qt’s OpenGL classes (QOpenGLWidget, QOpenGLShaderProgram, QOpenGLShader) (for my SDL project, I used GLM).  Finally, I used the cross-platform IDE Qt Creator (for my SDL project, I used Visual Studio for Windows, GCC for Linux, XCode for Mac OS X, XCode for iOS, Android SDK with ADT for Android).  So Qt made a lot of things simpler for this project.  The project’s C++ code is only about 1000 lines and one .ui file (note most of those lines are comments and formatting).  It was faster and easier to develop than the cross-platform SDL project.  The .pro build file (Qt qmake project file) is amazingly small (just a few lines).  I faced less platform-specific nuances, build setup, #ifdef’s, etc (with Qt versus my SDL project).

For volume, I summed the signed volume of a tetrahedron (for each triangle).  See (Efficient Feature Extraction for 2D/3D Objects in Mesh Representation, Cha Zhang and Tsuhan Chen ) ( https://stackoverflow.com/questions/1406029/how-to-calculate-the-volume-of-a-3d-mesh-object-the-surface-of-which-is-made-up –> http://research.microsoft.com/en-us/um/people/chazhang/publications/icip01_ChaZhang.pdf ) ( http://n-e-r-v-o-u-s.com/blog/?p=4415 ) .

For generating smooth normals…  STL specifies a triangle list with per-face normals (or we generate per-face normals).  We create a QHash that maps vertex position to (sum of un-normalized face normals).  The magnitude of cross product equals the area of a parallelogram with the vectors for sides, and that area is just double the area of the triangle.  Then we iterate the QHash (using the list of positions as the keys), and normalize each value (sum of un-normalized face normals), and append that value to the normals list (QVector<QVector3D>).

More on generating smooth normals…  If you look at my smooth normals screenshot, you’ll see that the cube doesn’t look very good – the lighting is strange and the edges look rounded.  Another idea I’ll plan to try later is an angle-weighted average.  Some links I found useful…

This post likes angle-weighted average:
http://meshlabstuff.blogspot.com/2009/04/on-computation-of-vertex-normals.html

This paper compares methods and seems to like MWA (mean weighted by angle):
http://users.tricity.wsu.edu/~bobl/personal/mypubs/2003_vertnorm_tvc.pdf

This post mentions more ideas (including weight-by-angle):
http://steve.hollasch.net/cgindex/geometry/surfnorm.html

This excellent tutorial argues that angle weights are better than area weights:
http://www.bytehazard.com/articles/vertnorm.html

This tutorial video describes using smooth shading for shallow angles:
https://www.youtube.com/watch?v=PMgjVJogIbc

Here’s another algorithm that uses angle as a threshold:
https://user.xmission.com/~nate/smooth.html

Generating normals should be a fun topic to learn more about.  It sounds like there might not be one standard simple solution.  So I’ll plan to look for more reading etc with searches like (research smooth normals) and (research generating normals).

Qt OpenGL notes

Notes on using OpenGL with Qt’s OpenGL, focus on Qt 5+ and QOpenGLWidget (not the older QGLWidget).  Qt’s QOpenGL* support offers integration with Qt, and aims to provide helper classes that make cross-platform development with Qt & OpenGL simpler & easier (faster development time).  QOpenGL* classes are based on OpenGL ES 2.0 and designed to be able to use ANGLE.  You can use a mix of QOpenGL* helpers with direct standard raw OpenGL calls.

Qt’s support to give an OpenGL context to display in a GUI with mouse/keyboard input (in this way it is similar to SDL or GLUT).  Qt also has helper classes for OpenGL, and you can still mix this with native gl*() function calls.  Qt OpenGL helpers reduces #ifdef’s for platforms and for OpenGL desktop vs. OpenGL ES, and also gives some convenience functionality (below I list some examples relating to core profiles, extensions, debug/log, timer, shader programs).

The actual notes I put here are not really designed to be useful to anyone, except maybe as a reference to myself to remind me of some stuff I read when first getting exposed to Qt’s integration with OpenGL.  This also just shows an example of some stuff I read, and how I sometimes use notes to help me organize my thoughts.  My brain can only hold so much at once, so I’ll often have lots of notes and to-do lists (paper and electronic).  The PDF notes I took on a plane without WiFi.

Qt with ANGLE (OpenGL ES 2.0) versus desktop OpenGL

Qt 5 uses ANGLE as the default renderer for its OpenGL ES 2.0 API wrapper.  This gives high performance OpenGL compatibility to Windows desktops by translating calls to Direct3D, which has better driver support.  The Direct3D 9.0c backend means it supports (AMD GPU from 2005) and (NVIDIA from 2004) on Windows.  If the host computer runs Windows 7+ (or Vista with update), then even if the host computer has no GPU (or limited GPU), ANGLE will call DirectX 11 which will use WARP.  Qt does not recommend using ANGLE for Windows XP.  Microsoft Windows XP ended mainstream support Apr 2009 and extended support Apr 2014.
* https://en.wikipedia.org/wiki/ANGLE_(software)
* http://qt-project.org/wiki/Qt-5-on-Windows-ANGLE-and-OpenGL
* https://en.wikipedia.org/wiki/Radeon_X1000_Series
* https://en.wikipedia.org/wiki/GeForce_6_series
* http://msdn.microsoft.com/en-us/library/windows/desktop/gg615082(v=vs.85).aspx

https://stackoverflow.com/questions/21722852/difference-in-opengl-speed-between-qt-4-5-and-opengl-api
* QOpenGLContext makes cross-platform OpenGL context easy (then you can use raw opengl if you want)
* Qt gives GUI and keyboard/mouse input
* helpers: QMatrix4x4, QOpenGLxxx (Context, Buffer, VAO, Texture, FBO, Shader, ShaderProgram, DebugLogger)
* eg QOpenGLVertexArrayObject points desktop to GL_ARB_vertex_array_object, ES to GL_OES_vertex_array_object
* some Qt OpenGL wrappers are lacking, but you can still use raw OpenGL code
* Qt comes with lots of cross-platform libraries besides GUI
* Qt 5 compile with "Desktop GL" or "ES 2"; warning ES 2 is different
* some Windows users don’t upgrade their GPU drivers, so OpenGL ES 2 with ANGLE helps by using Direct3D
* warning modern GL requires desktop OpenGL (ANGLE is currently only for OpenGL ES 2.0) (ES 3.0 in progress)
* Qt Quick has QML scripting language; Qt Quick renders GUI with OpenGL; relevant to mobile UI

https://stackoverflow.com/questions/15671816/opengl-vs-qopengl-qtopengl-in-qt-5-differences-and-limitations
* Qt 5’s OpenGL wrappers versus desktop OpenGL
* Qt 5’s OpenGL wrappers are built on top of OpenGL ES 2.0 to facilitate portability
* Using desktop OpenGL with Qt may require more development effort

http://qt-project.org/wiki/New-Features-in-Qt-5.4
* QGL* classes are deprecated since QGLWidget can now be replaced by QOpenGLWidget
* Dynamic OpenGL implementation selection on application startup is now available on Windows when configured with -opengl dynamic. This allows using either opengl32.dll or ANGLE’s OpenGL ES 2.0 implementation in Qt and applications without the need for two separate builds of the binaries.

OpenGL in Qt 5.1 introduction (from March 2013)

http://www.kdab.com/opengl-in-qt-5-1-part-1/
* Qt 5.0 use QOpenGLWidget (QOpenGL*) instead of older QGLWidget (QGL*)
* see QOpenGL* at http://doc-snapshot.qt-project.org/qt5-5.4/qtgui-module.html
* QOpenGLFunctions – common subset of OpenGL 2 & OpenGL ES 2
* QOpenGLContext::versionFunctions() – example getting OpenGL 4.3 core profile functions, QOpenGLFunctions_4_3_Core
* QOpenGLContext::hasExtension(), extensions() – check for supported extensions
* QOpenGLContext::getProcAddress() – perform manual resolution of entry points (OpenGL extension function) (simpler than GLEW, GLee)
* QtOpenGLExtensions – static lib with OpenGL extensions

http://www.kdab.com/opengl-in-qt-5-1-part-2/
* QOpenGLBuffer – per-vertex attribute data & element index buffers
* QOpenGLVertexArrayObject, VAO (Vertex Array Object) – manages a set of VBOs (vertex buffer objects), vertex layouts, IBO (Index Buffer Object)
* comments section (Grumpy OpenGL) questions whether one should use Qt GL wrapper classes, but suggest barriers to using pure OpenGL with Qt

http://www.kdab.com/opengl-in-qt-5-1-part-3/
* timer queries help analyze OpenGL (GPU) performance for profiling or adaptive rendering
* OpenGLTimerQuery simple wrapper on GL, QOpenGLTimeMonitor makes timer query easier

http://www.kdab.com/opengl-in-qt-5-1-part-4/
* traditional OpenGL debug uses glGetError(), recently GL_KHR_debug extension
* QOpenGLDebugLogger, messageLogged(), errors, info messages, use SIGNAL SLOT, simpler logging
* QOpenGLDebugLogger::SynchronousLogging mode allows you to break to stack with OpenGL function call error

http://www.kdab.com/opengl-in-qt-5-1-part-5/
* QOpenGLShader, QOpenGLShaderProgram
* example heightmap terrain
* QGuiApplication + QWindow + QOpenGLContext basically the same as GLUT or SDL
* code example mixes QOpenGL* helper classes with raw opengl gl*() calls such as glClear(), glDrawArrays(), glViewPort(), glEnable(), glClearColor()

Hello GL Example – included in Qt Creator Examples

http://qt-project.org/doc/qt-5/qtopengl-hellogl-example.html
* example uses QGLWidget (not the newer QOpenGLWidget)
* display OpenGL scene as a QWidget, use SIGNALs/SLOTs, mouse/keyboard input
* slots used for mouse GUI input to control rotation
* initializeGL() init, paintGL() draws, updateGL() triggers draw, resizeGL() updates viewport and projection matrix
* uses some legacy functions like glMatrixMode(), glLoadIdentity(), glOrthof(), glRotatef(), glMaterial() etc
* ex QtLogo class holds vertex data
* ex class Window (QWidget) is a container to hold the QGLWidget plus GUI sliders and keyboard input
* GUI sliders also connect() SIGNALs and SLOTs to control rotation
* QGLWidget is a QWidget, so you can also draw 2D on it with QPainter

https://www.opengl.org/wiki/Legacy_OpenGL
* lists some legacy functions to avoid

Introduction to using OpenGL, focus on using OpenGL with Qt

http://anychimirror101.mirrors.tds.net/pub/Qt/learning/developerguides/qtopengltutorial/OpenGLTutorial.pdf
* tutorial introduces (or reviews) basic OpenGL (computer graphics) concepts, and explains simple examples using Qt

* view volume, perspective projection, orthographic projectionm ch 2
* linear algebra: vec4 (x y z w), m4x4, affine transformations (translate scale rotate) (stretch shear reflect) (project)
* mat mul not commutative (order matters)
* coordinate system (frame concept, basis); eg model space, world space, camera space, screen space coordinates
* model-view-proj => normalized device coordinates x y z (-1 to 1)
* vert spec -> VS -> PA -> clip cull -> RS  -> FS -> Per Sample (OM) -> framebuffer/screen
* C++ GL* types, GL_* #define’s, gl*() functions
* GLSL types (vec4, mat4, sampler2D etc) (array, struct, xyzw rgba stpq)
* GLSL storage qualifiers (attribute, unform, in out (formerly varying))
* GLSL built-in variables gl_Position, gl_FragColor, FS can "discard", #version 330 etc
* GLSL main(), functions don’t return values – they use parameter qualifiers (in out inout)
* GLSL no recursion, no pointers, constant array indexes, for loop compile-time iteration count, type cast with constructor
* QGLWidget, implement initializeGL(), resizeGL() (viewport, projection), paintGL() renders scene; QT += opengl, ch 3
* ex class GlWidget : public QGLWidget, Q_OBJECT, QGLShaderProgram, QMatrix4x4, QVector<QVector3D> verts, QGLFormat, ch 3
* depth test, face cull, clear color; ex mixes glEnable(), qglClearColor(), QGLShaderProgram, QGLShader, QVector3D
* uniform mat4 mvpMatrix; in vec4 vertex; void main(void) { gl_Position = mvpMatrix * vertex); }
* uniform vec4 color; out vec4 fragColor; void main(void) { fragColor = color; }
* QMatrxi4x4::perspective() & glViewport() same aspect ratio
* QGLShaderProgram::bind(), setUniformValue(), setAttributeArray(), enableAttributeArray(), disableAttributeArray(), release()
* mouse input: implement QWidget::mousePressEvent(), mouseMoveEvent(), wheelEvent()
* QMatrix4x4::lookAt(), rotate(); ex rotate camera about origin while looking at origin (distance away from origin), ch 3.2
* VS: uniform mat4 mvpMatrix; in vec4 vertex; in vec4 color; out vec4 varyingColor; void main(void) { varyingColor = color; gl_Position = mvpMatrix * vertex; }
* FS: in vec4 varyingColor; out vec4 fragColor; void main(void) { fragColor = varyingColor; }
* C++: shaderProgram.setAttributeArray("color", colors.constData()); shaderProgram.enableAttributeArray("color"); … shaderProgram.disableAttributeArray("color");
* ex uses 12 triangles (3 vertes per triangle) for cube drawn with GL_TRIANGLES, ch 3.3
* textures (0,0) BL to (1,1) TR; glGenTextures(), glDeleteTextures(), glBindTexture() or QGLWidget::bindTexture(), GL_TEXTUREi, glActiveTexture(), ch 3.4
* VS: uniform mat4 mvpMatrix; in vec4 vertex; in vec2 textureCoordinate; out vec2 varyingTextureCoordinate;
  void main(void) { varyingTextureCoordinate = textureCoordinate; gl_Position = mvpMatrix * vertex; }
* FS: uniform sampler2D texture; in vec2 varyingTextureCoordinate; out vec4 fragColor;
  void main(void) { fragColor = texture2D(texture, varyingTextureCoordinate); }
* C++: QVector<QVector2D> textureCoordinates; GLuint texture; … texture = bindTexture(QPixmap(":/texture.png"));
* C++: setUniformValue() glBindTexture() setAttributeArray() enableAttributeArray() glDrawArrays() disableAttributeArray() release()
* ex defines glActiveTexture() manually via (#include <GL/glext.h>), but normally you would use GLEW (#include <GL/glew.h>), ch 3.4
* ex renders textured cube with Phong shading (based on light’s pos & color, object’s texture & material) & the light source, ch 3.5
* seperate shader programs for cube versus spotlight
* phong lighting equation uses ambient diffuse specular for each light & each object’s material (for ambient, diffuse, specular)
* diffuse uses normalized direction vector fragment to light & surface normal
* specular uses direction of light reflected at this point & vector from fragment to camera
* the vectors are calculated for each vertex in VS, then interpolated for FS … page 34
* ch 3.6 buffer object