<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Recent changes to Home</title><link>https://sourceforge.net/p/glslmath/wiki/Home/</link><description>Recent changes to Home</description><atom:link href="https://sourceforge.net/p/glslmath/wiki/Home/feed" rel="self"/><language>en</language><lastBuildDate>Sun, 15 Nov 2020 10:18:57 -0000</lastBuildDate><atom:link href="https://sourceforge.net/p/glslmath/wiki/Home/feed" rel="self" type="application/rss+xml"/><item><title>Home modified by Stefan Röttger</title><link>https://sourceforge.net/p/glslmath/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v20
+++ v21
@@ -1,9 +1,10 @@
-GLSLmath version 1.21 as of 11.February.2020
+GLSLmath version 1.21 as of 26.October.2020
 ----

-GLSLmath is free software. It is licensed under the MIT license.
-
-The code is copyright 2014-2020 by Stefan Roettger.
+GLSLmath is free software.
+It is distributed under the terms of the MIT license.
+
+The code is copyright (c) 2014-2020 by Stefan Roettger.
 Contact: snroettg at gmail

 ----
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefan Röttger</dc:creator><pubDate>Sun, 15 Nov 2020 10:18:57 -0000</pubDate><guid>https://sourceforge.netc8ab93434ec6857b38f68ee1faf9c549ad01612a</guid></item><item><title>Home modified by Stefan Röttger</title><link>https://sourceforge.net/p/glslmath/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v19
+++ v20
@@ -1,4 +1,4 @@
-GLSLmath version 1.20 as of 28.January.2020
+GLSLmath version 1.21 as of 11.February.2020
 ----

 GLSLmath is free software. It is licensed under the MIT license.
@@ -207,7 +207,7 @@
   norm of a vector v: norm(v)
   normalization of a vector v: normalize(v)
   reflection of a vector v at a surface normal n: reflect(v, n);
-  linear interpolation of two vectors a and b with factor w: lerp(w, a, b)
+  linear interpolation of two vectors a and b with factor w: lerp(w, a, b) resp. mix(a, b, w)
   blending two colors a and b: blend(a, b)

 * Creating a 3x3 identity matrix:
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefan Röttger</dc:creator><pubDate>Tue, 18 Feb 2020 23:28:50 -0000</pubDate><guid>https://sourceforge.netcb4e6b42c7305f971c05117f7b093464edd9d807</guid></item><item><title>Home modified by Stefan Röttger</title><link>https://sourceforge.net/p/glslmath/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v18
+++ v19
@@ -202,7 +202,7 @@
 * Procedural-style vector operations:

   length of a vector v: length(v)
-  dot product of two vectors a and b: dot(a, b) 
+  dot product of two vectors a and b: dot(a, b)
   cross product of two vectors a and b: cross(a, b)
   norm of a vector v: norm(v)
   normalization of a vector v: normalize(v)
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefan Röttger</dc:creator><pubDate>Tue, 28 Jan 2020 16:51:55 -0000</pubDate><guid>https://sourceforge.netacd27aba64c93b7576720c7b4ac4b054f5cd9460</guid></item><item><title>Home modified by Stefan Röttger</title><link>https://sourceforge.net/p/glslmath/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v17
+++ v18
@@ -1,2264 +1,512 @@
-glVertex version 5.0.8 as of 28.January.2020
+GLSLmath version 1.20 as of 28.January.2020
 ----

-The glVertex library is free software. It is licensed under
-the MIT license.
-
-The code is copyright 2015-2020 by Stefan Roettger.
+GLSLmath is free software. It is licensed under the MIT license.
+
+The code is copyright 2014-2020 by Stefan Roettger.
 Contact: snroettg at gmail

 ----

 INTRODUCTION:

-The glVertex software is a header-only C++ library.
-
-It is a convenience wrapper around OpenGL and GLSL. It also allows
-computer graphics developers to use the deprecated legacy OpenGL
-interface within a core profile. In particular it brings back the key
-concepts of the so called immediate mode.
+GLSLmath consists of a single C++ header file.
+
+It allows computer graphics developers to write math operations in C++
+just like one is used to it from GLSL. This includes support for a
+complete set of operators working on vector and matrix classes,
+homogeneous coordinates and quaternions. GLSLmath also features
+testing of geometric intersections between lines, triangles and
+ellipsoids.
+
+The software is easy to install and use, so it is ideal for rapid
+prototyping or teaching purposes. Supported platforms are Unix, MacOS
+X, Windows or any C++ 98 compatible compiler. GLSLmath is mature,
+regression-tested and afaik bug-free.

 ----

-BACKGROUND:
-
-In OpenGL 3.0 the legacy OpenGL interface was deprecated. This means
-that the so called fixed-function OpenGL pipeline was discarded in
-favor of a programmable pipeline model, which forces the use of vertex
-buffers and GLSL shaders. The main reasons behind this decision were
-rendering performance improvements, the reduction of driver complexity
-and an overall leaner OpenGL interface.
-
-As a result, the complete set of immediate mode OpenGL instructions
-like glVertex() and glColor() was removed from the OpenGL core
-profile. The immediate mode is still available in the OpenGL
-compatibility profile, but in practice this limits the computer
-graphics developer to OpenGL 2.1. If you want to use OpenGL 3.0 or
-higher, you do not have access to immediate mode any longer.
-
-The immediate mode was removed for good reasons. It allows experienced
-computer graphics developers to leverage the full power of vertex
-buffer objects and GLSL shaders. For OpenGL beginners, however, the
-already steep learning curve of OpenGL has become even steeper. What
-is more, there are still many situations, where the old legacy OpenGL
-interface would be helpful: Either for ease of implementation, rapid
-prototyping, teaching purposes or just for backwards
-compatibility. The same holds for all the use cases, where the
-limiting factor is not the vertex stage of the graphics pipeline. This
-includes volume rendering, image composing or any rasterization
-limited graphics algorithm. So there is clearly a need for legacy
-OpenGL even with modern GPUs.
+USAGE EXAMPLE:
+
+To install the GLSLmath header, run "sudo make install" in the
+directory of the distribution or simply copy the header to a location
+of your choice. By default the header is installed in
+"usr/local/include" on Linux platforms.
+
+Here is a usage example that declares a position vector in homogeneous
+coordinates and then scales, rotates and translates that vector by
+multiplying it with a corresponding 4x4 matrix:
+
+~~~~
+#include &amp;lt;glslmath.h&amp;gt;
+
+vec4 v(1,0,0);
+
+std::cout &amp;lt;&amp;lt; "original vector: " &amp;lt;&amp;lt; v &amp;lt;&amp;lt; std::endl;
+
+mat4 S = mat4::scale(3);
+mat4 R = mat4::rotate(90, vec3(0,1,0));
+mat4 T = mat4::translate(vec3(1,0,-10));
+mat4 M = T*R*S;
+
+v = M*v; // yields (1,0,-13)
+
+std::cout &amp;lt;&amp;lt; "transformed vector: " &amp;lt;&amp;lt; v &amp;lt;&amp;lt; std::endl;
+~~~~
+
+Note: GLSLmath has been inspired by the glm and slmath libraries,
+which aim to mimic GLSL, as well. In contrast to those, GLSLmath does
+not focus on a complete conforming implementation of GLSL. It rather
+aims to provide a convenient single header file that implements the
+most commonly used subset of linear algebra operations of GLSL so that
+it is easy to use for rapid prototyping and GLSL teaching purposes.

 ----

-GOALS:
-
-The glVertex library aims to bring back the legacy OpenGL
-fixed-function pipeline to ease the use of OpenGL core profiles. It
-tries not to provide a complete conforming implementation of the
-fixed-function pipeline, mainly for the same reasons why OpenGL 3.0
-does not support it any longer. Instead it tries to bring back the
-following key concepts of the fixed-function pipeline:
-
-* specification of vertices and attributes in immediate mode fashion
-* specification of perspective, modeling and viewing matrices in immediate mode fashion
-* matrix stack operations in immediate mode fashion
-* control over a subset of fixed-function features like
- * blinn-phong lighting
- * plain 2D and 3D texturing
- * depth testing and back-face culling
- * blending and alpha testing
- * multiple clip planes
- * fragment-based fog
- * and polygon mode
-
-This does not imply that rendering performance is compromised using
-the reenabled legacy OpenGL features. The glVertex library will map
-the legacy features to the fast paths available in the OpenGL core
-profile. For example, when specifying vertices in immediate mode, the
-vertices will be automatically added to a vertex buffer object under
-the hood. As a welcome side effect, the creation of vertex buffer
-objects (VBOs) and GLSL shaders is much simplified with the glVertex
-frame work.
-
-Summing up, the glVertex software aims to be easy to install and use,
-so that it is ideal for OpenGL beginners, rapid prototyping or
-teaching purposes. At the same time it is a frame work for efficient
-OpenGL and OpenGL ES development.
-
-Supported platforms are Unix, MacOS X, Windows and Android. The single
-dependency is OpenGL (resp. OpenGL ES on mobile platforms).
+PROGRAMMING API:
+
+* Creating a 3D vector:
+
+~~~~
+  vec3 v(0,0,-10);
+~~~~
+
+* Accessing the components of a 3D vector:
+
+~~~~
+  double x = v.x;
+  double y = v.y;
+  double z = v.z;
+~~~~
+
+* Printing a 3D vector:
+
+~~~~
+  std::cout &amp;lt;&amp;lt; "v = " &amp;lt;&amp;lt; v &amp;lt;&amp;lt; std::endl;
+   yields
+  "v = (0, 0, -10)"
+~~~~
+
+* Getting the length and norm of a vector:
+
+~~~~
+  vec3 v(0,3,4);
+  double l = v.length(); // yields 5
+  double l2 = v.norm(); // yields 25
+~~~~
+
+* Averaging two vectors p1 and p2:
+
+~~~~
+  vec3 p1(-10,0,0), p2(10,0,0);
+  vec3 v = 0.5*(p1+p2); // yields (0,0,0)
+~~~~
+
+* Linear interpolation of two vectors p1 and p2:
+
+  Let w be the linear interpolation factor in the range [0..1]:
+
+~~~~
+  vec3 p1(-10,0,0), p2(10,0,0);
+
+  double w = 0.5;
+  vec3 v = (1-w)*p1 + w*p2; // yields (0,0,0)
+~~~~
+
+* Calculating the dot product:
+
+~~~~
+  vec3 a(1,0,0), b(0,0,1);
+  double d = a.dot(b); // yields 0
+~~~~
+
+* Calculating the cross product:
+
+~~~~
+  vec3 a(1,0,0), b(0,0,1);
+  vec3 c = a.cross(b); // yields (0,-1,0)
+~~~~
+
+* Computing a normalized direction vector from two position vectors:
+
+~~~~
+  vec4 p1(0,20,0), p2(0,10,0);
+  vec4 d = (p2-p1).normalize(); // yields (0,-1,0)
+~~~~
+
+  Note that p1 and p2 are position vectors with homogeneous coordinate
+  w=1 and d is a direction vector with homogeneous coordinate w=0!
+
+* Component swizzeling:
+
+~~~~
+  vec4 a(1,2,3,4);
+  vec4 b(a.wzyx());      // yields (4,3,2,1)
+  vec4 c(b.zw(),b.xy()); // yields (2,1,4,3)
+~~~~
+
+* Calculating a normalized triangle normal from the three corners a,b,c:
+
+~~~~
+  vec3 normal = vec3::normal(a,b,c);
+~~~~
+
+* Calculating the area of a triangle with the three vertices a,b,c:
+
+~~~~
+  double area = vec3::area(a,b,c);
+~~~~
+
+* Computing the diffuse lighting term:
+
+  Let d be the direction vector of a light source and v1/v2/v3 the
+  three vertices of a triangle, then the diffuse lighting term is
+  calculated as follows:
+
+~~~~
+  vec3 n = (v2-v1).cross(v3-v1).normalize();
+  double term = fabs(d.dot(n));
+~~~~
+
+* Reflecting a light vector at a surface normal:
+
+  Let v be the incident light vector, let n be the normalized surface
+  normal pointing outwards, then the reflected vector r is computed as
+  follows:
+
+~~~~
+  vec3 v(1,-1,0);
+  vec3 n(0,1,0);
+
+  vec3 r = v.reflect(n); // yields (1,1,0)
+~~~~
+
+* Accessing the components of a color vector:
+
+~~~~
+  vec4 color(1,0,0);  // opaque red
+  double r = color.r; // r=1
+  double g = color.g; // g=0
+  double b = color.b; // b=0
+  double a = color.a; // a=1
+~~~~
+
+* Blending two colors:
+
+~~~~
+  vec4 color1(1,0,0);
+  vec4 color2(0,0,1, 0.25);
+  vec4 mix = color1.blend(color2); // yields (0.75,0,0.25,1)
+~~~~
+
+* Procedural-style vector operations:
+
+  length of a vector v: length(v)
+  dot product of two vectors a and b: dot(a, b) 
+  cross product of two vectors a and b: cross(a, b)
+  norm of a vector v: norm(v)
+  normalization of a vector v: normalize(v)
+  reflection of a vector v at a surface normal n: reflect(v, n);
+  linear interpolation of two vectors a and b with factor w: lerp(w, a, b)
+  blending two colors a and b: blend(a, b)
+
+* Creating a 3x3 identity matrix:
+
+~~~~
+  mat3 I;
+   or
+  mat3 M(1);
+~~~~
+
+* Printing a 3x3 matrix:
+
+~~~~
+  std::cout &amp;lt;&amp;lt; "I = " &amp;lt;&amp;lt; I &amp;lt;&amp;lt; std::endl;
+   yields
+  "I = ((1, 0, 0), (0, 1, 0), (0, 0, 1))"
+~~~~
+
+* Creating a 3x3 diagonal matrix:
+
+~~~~
+  mat3 D(vec3(1,2,3));
+~~~~
+
+* Getting the determinant of a 3x3 matrix:
+
+~~~~
+  double d = D.det();
+~~~~
+
+* Creating a 3x3 matrix from three row vectors and multiplying it with a vector:
+
+~~~~
+  mat3 M(vec3(0,1,0),
+         vec3(-1,0,0),
+         vec3(0,0,1));
+
+  vec3 v(-10,0,0);
+  v = M*v; // yields (0,10,0)
+~~~~
+
+* Pretty-printing a 3x3 matrix:
+
+~~~~
+  glslmath::print(M, "M");
+
+  prints:
+
+      /       0             1             0       \
+  M = |      -1             0             0       |
+      \       0             0             1       /
+~~~~
+
+* Creating a 3x3 matrix from three column resp. row vectors:
+
+~~~~
+  mat3 Mc = mat3::columns(vec3(a,b,c), vec3(d,e,f), vec3(g,h,i));
+  mat3 Mr = mat3::rows(a,b,c, d,e,f, g,h,i);
+~~~~
+
+* Creating an affine 4x4 matrix and multiplying it with a position vector:
+
+  The matrix transforms homogeneous points from the local coordinate
+  system to a coordinate system with the origin o and the coordinate
+  axis x, y and z:
+
+~~~~
+  vec3 o = vec3(3,3,3);
+  vec3 x = vec3(0,1,0);
+  vec3 y = vec3(0,0,1);
+  vec3 z = vec3(1,0,0);
+  mat4 T = mat4::transform(o,x,y,z);
+
+  vec4 v(1,0,0);
+  v = T*v; // yields (3,4,3,1)
+~~~~
+
+* Available 4x4 matrix transformations as defined by the OpenGL standard:
+
+  translation by a vector v: mat4::translate(v)
+  rotation about an axis a and an angle of d degrees: mat4::rotate(d, a)
+  scaling with a factor f: mat4::scale(f)
+
+* Procedural-style 4x4 matrix transformations:
+
+  translation by a vector v: translate(M, v)
+  rotation about an axis a and an angle of d degrees: rotate(M, d, a)
+  scaling with a factor f: scale(M, f)
+
+  The above procedures multiply the corresponding transformation
+  matrix onto a given matrix M (from the right-hand side).
+
+* Using mat4 for MVP calculations as defined by the OpenGL
+  standard. The resulting matrix is transferred with glUniform:
+
+~~~~
+  mat4 P = mat4::perspective(90,1,1,100);
+  mat4 V = mat4::lookat(vec3(0,3,10), vec3(0,0,0), vec3(0,1,0));
+  mat4 M = mat4::translate(0,0,-10) * mat4::rotate(90, vec3(0,1,0)) * mat4::scale(3);
+
+  mat4 MVP = P*V*M;
+
+  glUniformMatrix4fv(location, 1, GL_FALSE, (const float *)mat4f(MVP));
+~~~~
+
+  Note that the order of matrix multiplications is the reverse of the
+  logical order of the applied transformations.
+
+  Also note that linear math calculations are done with double
+  precision to avoid numerical instabilities, but the transfer of the
+  final matrix to the gpu is done with single precision float
+  accuracy!
+
+* By default, matrices are multiplied from the right-hand side, e.g.:
+
+~~~~
+  mat4 M = mat4::translate(0,0,-10);
+  M *= mat4::rotate(90, vec3(0,1,0)); // M = T*R
+~~~~
+
+  But matrices can also be multiplied from the left hand-side to
+  reverse the order of transformations:
+
+~~~~
+  mat4 M = mat4::translate(0,0,-10);
+  M &amp;lt;&amp;lt;= mat4::rotate(90, vec3(0,1,0)); // M = R*T
+~~~~
+
+* Calculating the inverse transpose of the MVP matrix (used for normal transformations):
+
+~~~~
+  mat4 M = MVP.invert().transpose();
+~~~~
+
+* Special matrices:
+
+The following matrices are supported as defined by the OpenGL standard:
+
+~~~~
+   // create orthographic projection matrix
+   mat4 Mo = mat4:ortho(left, right, bottom, top, near, far);
+
+   // create frustum projection matrix
+   mat4 Mf = mat4:frustum(left, right, bottom, top, near, far);
+~~~~
+
+For convenience, the following matrices can be constructed as well:
+
+~~~~
+   // create affine transformation matrix consisting of
+   // a rotation resp. non-singular matrix M and a translation vector v
+   mat4 Mt = mat4:transform(M, v);
+
+   // create parallel projection matrix defined by
+   // a plane point p and normal n and a projection direction vector v
+   mat4 Mp = mat4:parallel(p, n, d);
+~~~~
+
+* Procedural-style matrix operations:
+
+  determinant of a matrix M: determinant(M)
+  transposition of a matrix M: transpose(M)
+  inversion of a matrix M: inverse(M)
+
+* Hierarchical modeling with the scoped matrix stack:
+
+  Given the following scene graph with
+
+~~~~
+  + = root node
+  C = camera
+  T0-T2 = modeling transformations
+  G = geometry node
+
+        +
+       / \
+      /   \
+     T0    \
+      |     C
+      |
+      |
+     / \
+    /   \
+   T1   T2
+    \   /
+     \ /
+      |
+      |
+      |
+      G
+~~~~
+
+  Then the matrices needed to render the two instances of the geometry
+  node can be computed with the scoped matrix stack of GLSLmath:
+
+~~~~
+  mat4 V = mat4::lookat(C, ...);
+  mat4 P = mat4::perspective(...);
+
+  load_matrix(P*V);
+  {
+     mult_matrix_scoped(T0);
+     {
+        mult_matrix_scoped(T1);
+        glUniformMatrix4fv(location, 1, GL_FALSE, (const float *)mat4f(top_matrix()));
+        render(G);
+     }
+     {
+        mult_matrix_scoped(T2);
+        glUniformMatrix4fv(location, 1, GL_FALSE, (const float *)mat4f(top_matrix()));
+        render(G);
+     }
+  }
+~~~~
+
+* Hierarchical modeling with the OpenGL matrix stack:
+
+  Given a scene where a glPushMatrix/glPopMatrix pair is required:
+
+~~~~
+   glPushMatrix();
+   ...
+   glPopMatrix();
+~~~~
+
+  The above pair can be rewritten with the OpenGL scoped matrix stack:
+
+~~~~
+   {
+      glPushMatrixScoped();
+      ...
+   }
+~~~~
+
+* Quaternions:
+
+  Transformation of a vector by two consecutive rotations represented
+  as quaternions:
+
+~~~~
+  quat a = quat::rotate(10, vec3(0,1,0));
+  quat b = quat::rotate(80, vec3(0,1,0));
+  quat q = a*b;
+
+  vec3 v(1,0,0);
+  v = q*v; // yields (0,0,1)
+~~~~
+
+* HSV to RGB conversion:
+
+~~~~
+  vec3 rgb1 = glslmath::hsv2rgb(0,1,1); // red
+  vec3 rgb2 = glslmath::hsv2rgb(60,1,1); // yellow
+  vec3 rgb3 = glslmath::hsv2rgb(120,1,0.25); // dark green
+  vec3 rgb4 = glslmath::hsv2rgb(240,0.5,1); // blueish
+~~~~
+
+* 3D Perlin noise:
+
+~~~~
+  vec3 coord(0.5,0.5,0.5);
+  double noise_value = glslnoise::noise(coord);
+  vec3 noise_vector = glslnoise::noise3D(coord);
+~~~~
+
+* Ray/plane intersection testing:
+
+  Let p be the start point and d be the direction vector of a half ray
+  (denoted by [p-&amp;gt;d]). Then the distance l to a plane defined by a
+  point o on the plane and the plane normal n is:
+
+~~~~
+   vec3 p(0,0,0), d(1,1,1); // ray definition
+   vec3 o(1,0,0), n(1,0,0); // plane definition
+
+   double l = glslmath::intersect_ray_plane(p,d.normalize(), o,n); // signed euclidean distance
+
+   if (l!=DBL_MAX) // plane is not parallel to half ray
+      if (l&amp;gt;=0) // half ray hits plane in the right direction
+      {
+         vec h = p+l*d; // hit point
+         ...
+      }
+~~~~
+
+  Likewise, GLSLmath contains methods, which compute distances resp. intersections between:
+  * a point p and a line segment [a,b]: distance2line(p, a,b)
+  * a ray [p-&amp;gt;d] and an unit sphere: intersect_ray_unitsphere(p,d)
+  * a ray [p-&amp;gt;d] and an ellipsoid (o, r1/r2/r3): intersect_ray_ellipsoid(p,d, o,r1,r2,r3)
+  * a ray [o-&amp;gt;d] and a triangle [a,b,c]: ray_triangle_dist(o,d, a,b,c)
+  plus intersection tests between:
+  * a point p and a sphere (b,r^2): itest_point_sphere(p, b,r2)
+  * a ray [o-&amp;gt;d] and a sphere (b,r^2): itest_ray_sphere(o,d, b,r2)
+  * a ray [o-&amp;gt;d] and a cone: itest_cone_sphere(o,d, ...)
+  * a ray [o-&amp;gt;d] and a bounding box: itest_ray_bbox(o,d, ...)
+  * and some more ...

 ----

-REQUIREMENTS:
-
-The glVertex software depends on OpenGL. So in the following it is
-assumed that the OpenGL drivers and development libraries have been
-installed properly. Since the software is written in C++, a compiler
-such as GCC (Linux/Android), CLANG (MacOS X) or MSVC++ (Windows) is
-required also. Some of the examples given below additionally require
-GLUT, GLFW or Qt as windowing library.
-
-In order to perform an automatic installation of those dependencies
-and the glVertex library on Linux and MacOS X, please run the
-"install.sh" script from the command line:
-
-&amp;gt; ./install.sh
-
-If it finishes successfully, the instructions given below, which
-describe the manual installation of the glVertex library and its
-dependencies on the respective platforms, can be skipped.
-
-----
-
-SUPPORTED PLATFORMS AND REQUIRED PACKAGES:
-
-On Ubuntu 14.04 to 16.04 the installation command for the required packages is:
-&amp;gt; sudo apt-get install g++ cmake freeglut3-dev libglfw-dev libqt4-dev
-
-On Ubuntu 17.04 to 19.10 (resp. Debian 8) the installation command for the required packages is:
-&amp;gt; sudo apt-get install g++ cmake freeglut3-dev libglfw3-dev libqt4-dev
-
-On Linux Mint 18 the installation command for the required packages is:
-&amp;gt; sudo apt-get install g++ cmake freeglut3-dev libglfw3-dev libqt4-dev libqt4-opengl-dev
-
-On OpenSuse 11 to 15 the installation command for the required packages is:
-&amp;gt; sudo zypper install gcc-c++ cmake freeglut-devel libglfw-devel libqt4-devel
-
-On Fedora 19+ (resp. CentOs) the installation command for the required packages is:
-&amp;gt; sudo yum install gcc-c++ cmake freeglut-devel libglfw-devel libqt4-devel
-
-On Arch Linux (resp. Manjaro Linux) it is recommended to install the required packages with pacman:
-&amp;gt; sudo pacman -S gcc cmake freeglut glfw-x11 qt4
-
-On MacOS X 10.5 to 10.14 it is mandatory to install XCode first.
-Then we install the following required packages:
-&amp;gt; cmake, glfw, Qt
-
-On MacOS X 10.15 it is also required to install the XCode command line tools:
-&amp;gt; xcode-select --install
-
-For OpenGL ES development it is recommended to install Qt 5.7.1 with Android support from:
-&amp;gt; https://download.qt.io/archive/qt/5.7/5.7.1/qt-opensource-linux-x64-android-5.7.1.run
-Or we install the Qt 5.12.6 LTS release with Android support from:
-&amp;gt; https://download.qt.io/archive/qt/5.12/5.12.6/qt-opensource-linux-x64-5.12.6.run
-
-On Windows the installation is performed by downloading the CMake GUI
-and an appropriate Qt for Windows package based on MinGW:
-&amp;gt; https://download.qt.io/archive/qt/5.12/5.12.6/qt-opensource-windows-x86-5.12.6.exe
-
-Positively tested platforms are:
-* Debian 8.6
-* Ubuntu 9.10, 14.04, 16.04, 16.10, 17.04, 17.10, 18.04, 18.10, 19.04, 19.10
-* Linux Mint 18.1
-* OpenSuse 13.2, 15.1
-* MacOS X 10.5, 10.6, 10.10, 10.11, 10.12, 10.13, 10.14, 10.15
-* Android 5.0 to 7.1
-* Windows 7, 10
-
-Other platforms such as Fedora, CentOS (resp. RedHat / RHEL), Arch
-Linux (resp. Manjaro Linux) are principally supported, but those
-platforms are not tested in-depth.
-
-----
-
-INSTALLATION:
-
-The glVertex software is a C++ header-only library, so there is not
-much to do for installation purposes:
-
-To install the glVertex development headers, we simply run "sudo make
-install" in the directory of the distribution. By default the headers
-are installed in "/usr/local/include" on Linux platforms. To uninstall
-type "sudo make uninstall".
-
-The above installation procedure is equivalent to copying all headers
-(*.h) from the base distribution directory to a destination directory,
-so if you want to do a manual installation, it is as easy as this:
-
-&amp;gt; cp *.h destination/
-
-----
-
-ONLINE INSTALLER:
-
-The online installer will download the most recent glVertex package
-from the code repository and install the package with all its
-dependencies. Just download the "installer.sh" script and start it
-from the command line:
-
-&amp;gt; ./installer.sh
-
-Then the best way to start coding with the glVertex library is
-described in the quick start section. If you are interested in the
-full documentation, please read on.
-
-----
-
-USAGE PRELIMINARIES:
-
-To use the glVertex library, we need to include the "glvertex.h" C++
-header:
-
-~~~~
- #include &amp;lt;glvertex.h&amp;gt;
-~~~~
-
-While the glVertex library restitutes parts of the legacy OpenGL 1.2
-interface, it aims not to be perfectly compatible with it. To account
-for that, all functions of the glVertex library share a "lgl"
-prefix. So instead of writing
-
-~~~~
- glVertex3d(0,0,0); // C style
-~~~~
-
-we write
-
-~~~~
- lglVertex(0,0,0); // C++ style
-~~~~
-
-We may also use the vector and matrix classes of the
-[GLSLmath](glslmath.md) library:
-
-~~~~
- vec3 v(0,0,0);
- lglVertex(v);
-~~~~
-
-----
-
-USAGE EXAMPLE:
-
-Here is a usage example that renders a single triangle in immediate
-mode. Under the hood, the immediate mode calls are translated to the
-creation of according vertex buffers (VBOs) and GLSL shaders, which
-simulate the fixed functionality of the legacy OpenGL 1.2 interface:
-
-~~~~
-#include &amp;lt;glvertex.h&amp;gt;
-
-...
-
-// matrix setup
-lglMatrixMode(LGL_PROJECTION);
-lglLoadIdentity();
-lglPerspective(fovy, aspect, nearp, farp);
-lglMatrixMode(LGL_MODELVIEW);
-lglLoadIdentity();
-lglLookAt(0,0,1, 0,0,0, 0,1,0);
-
-// render triangle
-lglBegin(LGL_TRIANGLES);
-   lglColor(1,0,0);
-   lglVertex(-0.5,-0.5,0);
-   lglColor(0,1,0);
-   lglVertex(0.5,-0.5,0);
-   lglColor(0,0,1);
-   lglVertex(0,0.5,0);
-lglEnd();
-~~~~
-
-The above example is available with GLUT as windowing library. It does
-not yet use a core rendering profile. This is achieved with GLFW and
-Qt further below. To compile and run the GLUT example on the Unix or
-Mac command line type:
-
-&amp;gt; make glut &amp;amp;&amp;amp; ./glut_example
-
-Or use CMake to compile and run it on the Unix or Mac command line:
-
-&amp;gt; (cd examples; cmake . &amp;amp;&amp;amp; make &amp;amp;&amp;amp; ./glut_example)
-
-On Windows use the CMake GUI to create a VC++ project.
-
-----
-
-GLSLMATH USAGE:
-
-Internally, the glVertex package uses the GLSLmath library to perform
-linear math calculations such as the calculation of projection and
-viewing matrices.
-
-For example, the legacy-style matrix setup used in the previous
-example is equivalent to the following linear math calculations using
-[GLSLmath](glslmath.md):
-
-~~~~
-// look at world origin (0,0,0) from (0,0,2) with up being (0,1,0)
-mat4 MV = mat4::lookat(vec3(0,0,2), vec3(0,0,0), vec3(0,1,0));
-// camera perspective defining field-of-view etc.
-mat4 P = mat4::perspective(fovy, aspect, nearp, farp);
-
-// mvp matrix setup
-mat4 MVP = P * MV;
-lglLoadMatrix(MVP);
-~~~~
-
-----
-
-GLVERTEX QUICK START:
-
-If you cannot wait to get your hands on the glVertex frame work and
-write your own 3D graphics code, the Qt programming template in the
-"qt_template" directory is the best way to get started. The template
-"qt_template.cpp" just shows an empty window, which is waiting for you
-to fill in legacy-style OpenGL code in the marked section of the
-renderOpenGL() method. But before doing so, please run the installer
-by typing "./installer.sh" to make sure that the frame work has been
-installed properly. See also the quickstart sheet ("QUICKSTART.txt").
-
-As a starting point, it is recommended to uncomment the code that is
-provided in the marked section as a legacy-style programming
-example. This is achieved by opening the "qt_template.pro" file with
-Qt Creator. Then we apply the code changes in the editor pane and hit
-the green Run button to compile an start the modified program. At your
-option you may also type "cmake . &amp;amp;&amp;amp; make" to compile the example with
-CMake on the command line. Or type "qmake &amp;amp;&amp;amp; make" on the command line
-to compile with QMake.
-
-For a quick overview of the programming API, see the glVertex quick
-reference sheet ("QUICKREF.txt") and the GLSLmath documentation
-("glslmath.txt"). Or have a look at the code examples in the
-"qt_examples" directory.
-
-More details on the Qt framework used in the programming template are
-given in the section about "Qt Convenience Classes" further below. For
-now we concentrate on creating a core profile by using another
-graphics framework: GLFW.
-
-----
-
-OPENGL CORE PROFILE EXAMPLE:
-
-The following example renders a single triangle using an OpenGL core
-profile. We are using the GLFW library to create an OpenGL 3.2 core
-profile. The example is based on the "simple.c" example of GLFW with
-the following modifications: hints for GLFW were added to create an
-according core profile and the immediate mode gl calls were replaced
-with according lgl calls.
-
-~~~~
-#include &amp;lt;glvertex.h&amp;gt;
-
-#include &amp;lt;glfw glfw3.h=""&amp;gt;
-
-int main(void)
-{
-   GLFWwindow* window;
-
-   if (!glfwInit())
-      exit(EXIT_FAILURE);
-
-   glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-   glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
-   glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
-   glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-
-   window = glfwCreateWindow(640, 480, "glVertex GLFW Example", NULL, NULL);
-
-   glfwMakeContextCurrent(window);
-   glfwSwapInterval(1);
-
-   while (!glfwWindowShouldClose(window))
-   {
-      int width, height;
-
-      glfwGetFramebufferSize(window, &amp;amp;width, &amp;amp;height);
-
-      double fovy = 90;
-      double aspect = (double)width/height;
-      double nearp = 0.1;
-      double farp = 10;
-
-      // clear frame buffer
-      glViewport(0, 0, width, height);
-      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-      glEnable(GL_DEPTH_TEST);
-      glDisble(GL_CULL_FACE);
-
-      // matrix setup
-      lglMatrixMode(LGL_PROJECTION);
-      lglLoadIdentity();
-      lglPerspective(fovy, aspect, nearp, farp);
-      lglMatrixMode(LGL_MODELVIEW);
-      lglLoadIdentity();
-      lglLookAt(0,0,1, 0,0,0, 0,1,0);
-
-      // render triangle
-      lglBegin(LGL_TRIANGLES);
-         lglColor(1,0,0);
-         lglVertex(-0.5,-0.5,0);
-         lglColor(0,1,0);
-         lglVertex(0.5,-0.5,0);
-         lglColor(0,0,1);
-         lglVertex(0,0.5,0);
-      lglEnd();
-
-      // swap frame buffer
-      glfwSwapBuffers(window);
-      glfwPollEvents();
-   }
-
-   glfwDestroyWindow(window);
-
-   glfwTerminate();
-   exit(EXIT_SUCCESS);
-}
-~~~~
-
-To compile and run the GLFW example on the command line type:
-
-&amp;gt; make glfw &amp;amp;&amp;amp; ./glfw_example
-
-----
-
-VBO USAGE EXAMPLE:
-
-Besides simulating the fixed function pipeline, the glVertex library
-is also handy for creating VBOs in the style of the legacy interface:
-
-~~~~
-#include &amp;lt;glvertex.h&amp;gt;
-
-...
-
-// declare vbo
-lglVBO vbo;
-
-...
-
-// compile vbo
-vbo.lglBegin(LGL_TRIANGLES);
-   vbo.lglColor(1,0,0);
-   vbo.lglVertex(-0.5,-0.5,0);
-   vbo.lglColor(0,1,0);
-   vbo.lglVertex(0.5,-0.5,0);
-   vbo.lglColor(0,0,1);
-   vbo.lglVertex(0,0.5,0);
-vbo.lglEnd();
-
-...
-
-// render vbo instance at position a
-lglPushMatrix();
-lglTranslate(a);
-vbo.lglRender();
-lglPopMatrix();
-
-// render vbo instance at position b
-lglPushMatrix();
-lglTranslate(b);
-vbo.lglRender();
-lglPopMatrix();
-~~~~
-
-Using the scoped matrix stack of glVertex, the above matrix operations
-can be rewritten as follows:
-
-~~~~
-{
-   // render vbo instance at position a
-   lglPushMatrixScoped();
-   lglTranslate(a);
-   vbo.lglRender();
-}
-
-{
-   // render vbo instance at position b
-   lglPushMatrixScoped();
-   lglTranslate(b);
-   vbo.lglRender();
-}
-~~~~
-
-The compiled vertices are stored in the VBO with double precision by
-default. The attributes are stored with float precision. For OpenGL ES
-the precision is float for both.
-
-In order to use only float precision for the compiled vertices, we use
-the lglVBOf class instead of lglVBO.
-
-----
-
-PRE-DEFINED VBOS:
-
-For convenience, the following geometric objects are available as
-predefined VBOs (meaning that they are derived from lglVBO as base class):
-
-* lglCube: unit cube
-* lglWireCube: unit wireframe cube
-* lglBox: rectangular box
-* lglTet: unit tetrahedron
-* lglPyramid: unit pyramid
-* lglPyramidBase: unit pyramid base
-* lglPrism: slanted unit prism
-* lglSphere: unit sphere
-* lglHemisphere: unit hemisphere
-* lglCylinder: unit cylinder
-* lglHemiCylinder: unit hemi-cylinder
-* lglDisc: unit disc
-* lglHemiDisc: unit hemi-disc
-* lglCone: unit cone
-* lglConeBase: unit cone base
-* lglRing: ring geometry
-* lglArc: arc geometry
-* lglTorus: unit torus
-* lglHemiTorus: unit hemi-torus
-* lglObj: pre-loaded geometry from an OBJ file
-* lglTeapot: the Melitta resp. Utah teapot
-* lglCoordSys: colored unit coordinate system axis
-
-The above predefined vertex buffer objects (except the predefined
-coordinate system axis) do not contain color attributes but outward
-facing normals and texture coordinates, so that they can be textured
-and shaded using ambient, diffuse and specular Blinn-Phong
-lighting. By default the light is a white directional light source
-positioned at the eye point. This means that the objects appear to be
-lit by a white head light.
-
-----
-
-PRE-DEFINED VBO EXAMPLE:
-
-As an example for pre-defined VBOs, the following code snippet renders
-a red shaded unit sphere at position p:
-
-~~~~
-// instantiate predefined sphere vbo
-lglSphere sphere;
-
-...
-
-{
-   // render red sphere instance at position p
-   lglPushMatrixScoped();
-   lglTranslate(p);
-   lglColor(1,0,0);
-   sphere.lglRender();
-}
-~~~~
-
-The usage of VBOs as shown above is demonstrated in the VBO
-example. To compile and run the example on the command line type:
-
-&amp;gt; make vbo &amp;amp;&amp;amp; ./vbo_example
-
-----
-
-TRIANGLE STRIPPING EXAMPLE:
-
-In case we want to compile a couple of triangle or quad strips into a
-VBO, we need to use a trick to combine the strips into a single
-VBO. The trick employed by the glVertex library is to add degenerate
-triangles between the strips so that they form a single batch. As a
-nice side effect, this is also the fastest rendering option to my
-knowledge (depending on the particular GPU hardware, ram and drivers
-there might be faster rendering options, but this cannot be
-generalized without a-priori knowledge of the actual rendering
-setup). Here is an example:
-
-~~~~
-lglVBO vbo;
-
-vbo.lglBegin(LGL_TRIANGLE_STRIP);
-   vbo.lglVertex(0,0,0);
-   vbo.lglVertex(0,1,0);
-   vbo.lglVertex(1,0,0);
-   vbo.lglVertex(1,1,0);
-   vbo.lglVertex(2,0,0);
-   vbo.lglVertex(2,1,0);
-vbo.lglEnd();
-vbo.lglBegin(LGL_TRIANGLE_STRIP);
-   vbo.lglVertex(0,1,0);
-   vbo.lglVertex(0,2,0);
-   vbo.lglVertex(1,1,0);
-   vbo.lglVertex(1,2,0);
-   vbo.lglVertex(2,1,0);
-   vbo.lglVertex(2,2,0);
-vbo.lglEnd();
-~~~~
-
-In between the two strips, the glVertex library automatically inserts
-the two vertices
-~~~~
-   vbo.lglVertex(2,1,0);
-   vbo.lglVertex(0,1,0);
-~~~~
-so that the two strips are effectively identical to the following
-single strip:
-~~~~
-vbo.lglBegin(LGL_TRIANGLE_STRIP);
-   vbo.lglVertex(0,0,0);
-   vbo.lglVertex(0,1,0);
-   vbo.lglVertex(1,0,0);
-   vbo.lglVertex(1,1,0);
-   vbo.lglVertex(2,0,0);
-   vbo.lglVertex(2,1,0);
-   vbo.lglVertex(2,1,0);
-   vbo.lglVertex(0,1,0);
-   vbo.lglVertex(0,1,0);
-   vbo.lglVertex(0,2,0);
-   vbo.lglVertex(1,1,0);
-   vbo.lglVertex(1,2,0);
-   vbo.lglVertex(2,1,0);
-   vbo.lglVertex(2,2,0);
-vbo.lglEnd();
-~~~~
-
-In the latter case, two degenerate triangles were created
-additionally. These are detected and discarded automatically by the
-graphics hardware. As a result, the triangle strip appears to be
-restarting in the middle. Even though we are generating two more
-triangles, the single strip can be rendered faster by the GPU, because
-it does not require another render call on the CPU side to start the
-next strip explicitly.
-
-The above principle is demonstrated in the mesh example. It constructs
-a triangle mesh from multiple triangle strips. To compile and run the
-example on the command line type:
-
-&amp;gt; make mesh &amp;amp;&amp;amp; ./mesh_example
-
-----
-
-PROGRAMMING API:
-
-In accordance with the legacy OpenGL 1.2 specification, the glVertex
-library supports the following API functions:
-* lglBegin, lglEnd
-* lglVertex, lglColor, lglNormal, lglTexCoord
-* lglMatrixMode, lglLoadIdentity, lglLoadMatrix, lglMultMatrix
-* lglScale, lglTranslate, lglRotate
-* lglOrtho, lglFrustum, lglPerspective, lglLookAt
-* lglPushMatrix, lglPopMatrix
-* lglViewport
-* lglClearColor, lglClear
-* lglLight
-* lglClipPlane
-* lglFog
-* lglLineWidth
-* lglPolygonMode
-* lglGetError
-
-Additionally, it supports the following extended convenience functions:
-* lglGetGLVersion, lglGetGLSLVersion
-* lglGetRenderer, lglGetVendor, lglGetVendorName
-* lglGetColor
-* lglAttribute
-* lglGetMatrixMode, lglGetMatrix
-* lglGetProjectionMatrix, lglGetModelViewMatrix, lglGetTextureMatrix
-* lglGetInverseModelViewMatrix, lglGetInverseTransposeModelViewMatrix
-* lglGetModelViewProjectionMatrix
-* lglRotateX, lglRotateY, lglRotateZ
-* lglParallel
-* lglProjection, lglModelView, lglView, lglTexture
-* lglManip, lglResetManip, lglIsManipApplied
-* lglGetManip, lglGetInverseTransposeManip
-* lglModel, lglGetModelMatrix, lglGetInverseTransposeModelMatrix
-* lglTex, lglGetTexMatrix
-* lglReadFile, lglReadTextFile
-* lglReadPnmImage, lglWritePnmImage
-* lglReadRawImage, lglWriteRawImage
-* lglSupportsGLSL, lglGetGLSLVersionString
-* lglCompileGLSLVertexShader, lglCompileGLSLFragmentShader, lglDeleteShader
-* lglCombineGLSLProgram, lglSplitGLSLProgram
-* lglCompileGLSLProgram, lglLinkGLSLProgram, lglDeleteGLSLProgram
-* lglLoadGLSLProgram, lglPlainGLSLProgram
-* lglUseProgram, lglReuseProgram, lglUseDefaultProgram
-* lglGetProgram, lglGetActiveProgram
-* lglUniform, lglUniformi, lglUniformf, lglUniformfv
-* lglSampler, lglSampler2D, lglSampler3D
-* lglLightDirection, lglLightPosition
-* lglLightVector, lglGetLightVector
-* lglLightParameters, lglGetLightParameters
-* lglLightSourceParameters, lglGetLightSourceParameters
-* lglMaterialParameters, lglGetMaterialParameters
-* lglTexture2D, lglGetTexture2D
-* lglTexture3D, lglGetTexture3D
-* lglCreateTexmap2D, lglCreateMipmap2D
-* lglCreateTexmap3D, lglCreateNoiseTexmap3D
-* lglDeleteTexmap
-* lglTexCoordGen, lglGetTexCoordGen
-* lglTexMagFilter2D, lglTexWrap2D, lglTexFilterAnisotropic2D
-* lglTexMagFilter3D, lglTexWrap3D, lglTexFilterAnisotropic3D
-* lglLoadTexture, lglLoadQtTexture
-* lglLoadObj, lglSaveObj
-* lglColoring, lglLighting, lglTexturing
-* lglGetColoring, lglGetLighting, lglGetTexturing
-* lglCloneUniforms, lglCopyUniforms
-* lglCloneProgram, lglCopyProgram
-* lglCloneState
-* lglInitializeOpenGL
-* lglRGBAWrite, lglGetRGBAWrite
-* lglZWrite, lglGetZWrite
-* lglDepthTest, lglGetDepthTest
-* lglBackFaceCulling, lglGetBackFaceCulling
-* lglBlendMode, lglGetBlending, lglGetBlendMode
-* lglAlphaTest, lglGetAlphaTest, lglGetAlphaTestValue
-* lglGetAlphaTestGreater, lglGetAlphaTestEqual
-* lglGetClipPlane, lglGetClipPlaneEquation
-* lglGetFog, lglGetFogDensity, lglGetFogColor
-* lglGetLineWidth
-* lglTogglePolygonMode, lglGetPolygonMode
-* lglInterlacingMode, lglComplementaryInterlacingMode, lglGetInterlacingMode
-* lglReadRGBPixels
-* lglBeginRayCast, lglRayCast, lglEndRayCast, lglGetRayCastDistance
-* lglEnableViewCulling, lglDisableViewCulling
-* lglRandom, lglSeed
-* lglWarning, lglError, lglFatal
-* lglVerbosity
-
-Additionally, the VBO classes support the following methods:
-* lglGetVertexMode, lglGetVertexCount
-* lglGetBoundingBox, lglGetCenter, lglGetExtent
-* lglGetBoundingSphere, lglGetRadius, lglGetNorm
-* lglGetMaxExtent, lglGetMaxAbsCoord
-* lglRender
-
-The following VBO classes are provided:
-* lglVBO (base class)
-* lglVBOf (uses float instead of double for storing vertices)
-* lglSharedVBO (multiple shared instances with transformation matrices)
-* lglCube, lglWireCube, lglBox, lglTet, lglPyramid, lglPyramidBase, lglPrism
-* lglSphere, lglHemisphere, lglCylinder, lglHemiCylinder
-* lglDisc, lglHemiDisc, lglCone, lglConeBase, lglRing, lglArc
-* lglTorus, lglHemiTorus
-* lglSheet, lglSheetBezier, lglSheetDisc
-* lglShim, lglSpiral, lglGear
-* lglFunctional, lglRotational, lglRotationalBezier
-* lglCylindrical, lglSpherical, lglToroidal
-* lglExtrusion, lglExtrusionBezier, lglReplicatedGeometry
-* lglPlanar, lglPlanarBezier
-* lglObj, lglTeapot
-* lglCoordSys
-
-Note: The lglLoadObj method and the lglObj and lglTeapot classes load
-OBJ data from /usr/local/share, if no data is present in the current
-working directory.
-
-----
-
-DETAILED API DESCRIPTION:
-
-The basic behavior of the glVertex API is closely related to the
-immediate mode and the fixed function pipeline of legacy OpenGL:
-
-* All legacy OpenGL modeling transformations like glTranslate(),
-  glRotate() and glScale() work as usual (except for using the "lgl"
-  instead of the "gl" prefix).
-
-* The same holds for matrix mode operations via lglMatrixMode() and
-  the matrix stack via lglPushMatrix() and lglPopMatrix(). For the
-  latter operations the matrix mode can be LGL_PROJECTION,
-  LGL_MODELVIEW or LGL_TEXTURE.
-
-* Projection and viewing matrices can be calculated using the
-  lglPerspective(), lglOrtho(), lglFrustum() and lglLookAt()
-  methods. This corresponds to the former GL and GLU utility methods
-  gluPerspective(), glOrtho(), gluOrtho2D, glFrustum and gluLookAt().
-
-* For the calculation of the above 4x4 matrices the glVertex library
-  is utilizing the GLSLmath C++ header-only math library, which is
-  part of the distribution.
-
-* For convenience, the library extends the above API with the
-  lglProjection(), lglModelView(), lglView() and lglModel()
-  methods. These simplify the setup of the model-view and projection
-  matrices, since they do not require an explicit change of the matrix
-  mode.
-
-* Matrix operations between lglBegin() and lglEnd() are not allowed.
-
-* Vertices are specified with lglVertex() after starting a sequence
-  with lglBegin(). The specified vertices are gathered in a VBO, which
-  is rendered on lglEnd(). Supported graphics primitives are:
-
-  * LGL_LINES, LGL_LINE_STRIP
-  * LGL_TRIANGLES, LGL_TRIANGLE_STRIP, LGL_TRIANGLE_FAN
-  * LGL_QUADS, LGL_QUAD_STRIP
-
-* If the vertices are gathered in an C++ object of type "lglVBO", they
-  are not rendered immediately on lglEnd() but on an explicit
-  lglRender() call. This enables multiple render calls on the same
-  pre-compiled VBO. The center of the vertices' bounding box is
-  available via lglGetCenter() and the extent of the bounding box is
-  available via lglGetExtent().
-
-* In the above case, multiple lglBegin() / lglEnd() sections are
-  allowed, if the primitive types are matching. If the primitive type
-  is LGL_TRIANGLE_STRIP or LGL_QUAD_STRIP, then the strip sections are
-  concatenated to form a single strip by adding degenerate triangles
-  between the strip sections. This is the fastest available rendering
-  option, since it allows to maximize the number of triangles sent to
-  the graphics pipeline in a single batch.
-
-* In the above case, it is allowed to perform matrix operations
-  between lglBegin() and lglEnd(), if the matrix mode is set to
-  LGL_PREMODEL. In that case, all vertices are immediately
-  pre-multiplied with the top matrix of the pre-model matrix stack.
-
-* In the above case, the "lglSharedVBO" container class allows to
-  organize multiple instances of the same shared VBO so that it is
-  rendered at different locations. Each matrix appended to the
-  container via push_back yields another shared VBO object.
-
-* Vertex attributes are specified via lglColor(), lglNormal() and
-  lglTexCoord() before lglVertex().
-
-* Attributes specified outside of lglBegin() and lglEnd() do not take
-  effect, except for colors. If colors are specified outside of
-  lglBegin() and lglEnd() those colors modulate the colors specified
-  in between. The default vertex color is white. The effect of
-  coloring can be disabled with lglColoring(false).
-
-* The wireframe silhouette of each rendered triangle can be displayed
-  by setting the polygon mode to LGL_LINE via lglPolygonMode().
-
-* With lglManip() a simple track ball can be implemented. By mapping
-  mouse deltas to rotating angles and passing them to lglManip(), the
-  scene will be displayed rotated about an anchor point in viewing
-  coordinates. By default the scene rotates around the lookat point as
-  specified by lglLookAt() or lglView(). The corresponding rotation
-  matrix is available via lglGetManip()
-  resp. lglGetInverseTransposeManip(), if provided by the windowing
-  subsystem (e.g. Qt).
-
-* The specification of per-vertex colors (with lglColor) automatically
-  triggers the setup of a default GLSL shader, which interpolates the
-  colors during rasterization. Further lighting or texturing
-  operations modulate that color.
-
-* The specification of per-vertex normals (with lglNormal)
-  automatically triggers the setup of a default GLSL shader, which
-  performs Blinn-Phong shading. The latter can be configured with the
-  lglLight() method, which takes the usual Blinn-Phong lighting terms
-  as parameters for a single directional or positional light
-  source. If the light source is not defined to be a camera light, the
-  light vector is multiplied with the inverse transpose of the actual
-  model-view matrix. To define the light vector in world coordinates,
-  the model-view matrix must therefore contain the viewing matrix. The
-  default setting is a white directional light source positioned at
-  the origin of the camera coordinate system, which modulates the
-  vertex colors. The effect of lighting can be disabled with
-  lglLighting(false).
-
-* The specification of per-vertex texture coordinates (with
-  lglTexCoord) automatically triggers legacy 2D resp. 3D texturing
-  using a corresponding default GLSL shader. This requires the
-  specification of a texture object via lglTexture2D() or
-  lglTexture3D(). Texture objects can be created either as plain
-  texture map via lglCreateTexmap2D() or as mip-mapped texture via
-  lglCreateMipmap2D(). Volumetric textures are created with
-  lglCreateTexmap3D(). Texture coordinates are multiplied with the top
-  matrix of the texture matrix stack. For convenience, we can specify
-  the texture matrix via lglTex() without explicitly setting the
-  matrix mode to LGL_TEXTURE. The texture color is always modulating
-  the vertex color. The effect of texturing can be disabled with
-  lglTexturing(false).
-
-* If texture coordinate generation is turned on via lglTexCoordGen(),
-  then vertex positions are automatically interpreted as texture
-  coordinates, meaning that texture coordinates are identical to
-  object space coordinates. This is helpful for procedural
-  texturing. For this use case a 3D Perlin noise texture can be
-  created with lglCreateNoiseTexmap3D().
-
-* Clip planes are specified identically to the legacy OpenGL 1.2
-  specification by passing the coefficients a, b, c and d of the clip
-  plane equation ax+by+cz+d=0 to lglClipPlane(a, b, c, d, n), where n
-  is the number of the clip plane to be used. Up to 8 clip planes are
-  supported by default.
-
-* Fog parameters can be specified with lglFog(d, c). The first
-  parameter d controls the density of the fog, whereas the second
-  parameter c defines the fog color. If the density is zero, fog is
-  disabled. The fog factor f being used for blending with the fog
-  color is:
-
-  * w = 1/gl_FragCoord.w
-  * f = 1-exp(-density*w*w)
-
-* The state of the OpenGL rasterization can be controlled with the
-  following convenience functions: lglDepthDest(),
-  lglBackFaceCulling(), lglBlendMode(), lglAlphaTest(), lglRGBAWrite,
-  lglZWrite and lglLineWidth().
-
-* To specify a custom GLSL shader, we compile or load a shader via
-  lglCompileGLSLProgram() resp. lglLoadGLSLProgram() and pass the
-  corresponding GLSL program id to lglUseProgram(). Generic vertex
-  attributes to be used by the custom shader are specified with
-  lglAttribute() within lglBegin() / lglEnd() sections. Uniform shader
-  variables are set with lglUniform*(). The usage of the custom shader
-  and uniforms is limited to the VBO on which the shader and uniforms
-  have been set locally. Uniforms can be copied from one VBO to
-  another by calling lglCopyUniforms(). To render a VBO with a custom
-  program and a local set of uniforms, call vbo.lglUseProgram(),
-  vbo.lglUniform() and vbo.lglRender() on the VBO object "vbo". To
-  render a set of VBOs with a consistent program and set of uniforms,
-  call lglUseProgram(), lglUniform() and lglRender(vbo) globally. To
-  disable a custom shader, call lglUseDefaultProgram(). The disposal
-  of unused custom shaders needs to be handled explicitly via
-  lglDeleteGLSLProgram().
-
-* To replace the internal default shader, which is used if no custom
-  shader is specified, we pass a compiled program id to
-  lglReplaceDefaultProgram(id, colors, normals, texcoords), where the
-  latter three parameters determine whether or not the shader is
-  taylored for receiving color, normal or texture coordinate
-  attributes as attached to the actually rendered vertices. The
-  replaced shader will be active for all VBOs, which have no custom
-  shader and match the specified set of vertex attributes. A
-  replacement shader can be specified for each different set of
-  attributes (meaning a total of 8 auto-selected replacement
-  shaders). It is recommended to use VBOs with normals but no color or
-  texture coordinate attributes by default and specify a replacement
-  shader for this default attribute set via
-  lglReplaceDefaultProgram(id).
-
-For more information about GLSL shaders see the following examples:
-
-----
-
-GLSL SHADER EXAMPLE:
-
-If both color and normal attributes are supplied along each vertex,
-the glVertex library uses the following default GLSL shader (which has
-been simplified to make it better readable), which performs
-single-sided Blinn-Phong shading for either a directional or a
-positional light source:
-
-Default Vertex Shader:
-
-~~~~
-#version 120
-attribute vec4 vertex_position;
-attribute vec4 vertex_color;
-attribute vec3 vertex_normal;
-uniform mat4 mv;
-uniform mat4 mvp;
-uniform mat4 mvit;
-uniform vec4 light;
-varying vec4 frag_color;
-varying vec3 frag_normal;
-varying vec3 frag_halfway;
-varying vec3 frag_lightvec;
-vec3 flightvec(vec4 mv_pos) {return((light.w==0.0f)? vec3(light) : vec3(light - mv_pos));}
-vec3 flightdir(vec4 mv_pos) {return((light.w==0.0f)? vec3(light) : normalize(vec3(light - mv_pos)));}
-vec4 fvertex() {return(mvp * vertex_position);}
-vec3 fnormal() {return(normalize(mat3(mvit) * vertex_normal));}
-vec3 fhalfway(vec4 mv_pos) {return(normalize(flightdir(mv_pos) - normalize(vec3(mv_pos))));}
-void main()
-{
-   vec4 mv_pos = mv * vertex_position;
-   frag_color = vertex_color;
-   frag_normal = fnormal();
-   frag_halfway = fhalfway(mv_pos);
-   frag_lightvec = flightvec(mv_pos);
-   gl_Position = fvertex();
-}
-~~~~
-
-Default Fragment Shader:
-
-~~~~
-#version 120
-uniform vec3 kaIa,kdId,ksIs;
-uniform float exponent;
-uniform vec3 falloff;
-varying vec4 frag_color;
-varying vec3 frag_normal;
-varying vec3 frag_halfway;
-varying vec3 frag_lightvec;
-vec4 flighting(vec4 color)
-{
-   vec3 n = normalize(frag_normal);
-   vec3 h = normalize(frag_halfway);
-   vec3 l = normalize(frag_lightvec);
-   float d = length(frag_lightvec);
-   float diffuse = dot(l, n);
-   float specular = dot(h, n);
-   float attenuation = 1.0f / (falloff.x + falloff.y*d + falloff.z*d*d);
-   diffuse = (diffuse &amp;lt; 0.0f)? 0.0f : diffuse;
-   specular = pow((specular &amp;lt; 0.0f)? 0.0f : specular, exponent);
-   attenuation = (attenuation &amp;gt; 1.0f)? 1.0f : attenuation;
-   return(vec4(vec3(color) * (kaIa + kdId * diffuse * attenuation) + ksIs * specular * attenuation, color.a));
-}
-void main()
-{
-   gl_FragColor = flighting(frag_color);
-}
-~~~~
-
-If the polygon mode is set to LGL_LINE with lglPolygonMode(), the
-above shaders are replaced with a single-pass GLSL shader that
-calculates the wire frame silhouette of each triangle by using
-barycentric coordinates.
-
-The default shader can be overridden by setting a custom GLSL shader
-via lglUseProgram(). Then the GLSL program must comply to the
-following rules:
-
-* Vertices are passed in the attribute "vertex_position" (vec4).
-* Colors are passed in the attribute "vertex_color" (vec4).
-* Normals are passed in the attribute "vertex_normal" (vec3).
-* Texture coordinates are passed in the attribute "vertex_texcoord" (vec4).
-* Generic vertex attributes are passed in "vertex_attribute0",
-  "vertex_attribute1", "vertex_attribute2", ...
-* The vertex shader is required to use the model-view-projection
-  matrix "mvp" and transform the vertices with that matrix (uniform
-  mat4 mvp).
-* If no color attributes were specified between lglBegin() and
-  lglEnd(), the fragment shader may use the actual color instead
-  (uniform vec4 color).
-* If normals were specified, the vertex shader may use the model-view
-  matrix "mv" resp. the inverse transpose model-view matrix "mvit" to
-  transform the vertex normals.
-* If texture coordinates were specified, the vertex shader may use the
-  uniform texture matrix "tm" and transform texture coordinates with
-  that matrix.
-* The vertex shader is required to write "gl_Position".
-* The fragment shader is required to write "gl_FragColor".
-
-To setup a custom shader, we can load the GLSL source like so:
-
-~~~~
-const char vertex_shader_file[] = "vertex_shader.frg";
-const char fragment_shader_file[] = "fragment_shader.vtx";
-...
-GLuint program = lglLoadGLSLProgram(vertex_shader_file, fragment_shader_file);
-lglUseProgram(program);
-...
-lglDeleteGLSLProgram(program);
-~~~~
-
-If the shader sources are available as a single shader file with the
-extension ".glsl", where the vertex and fragment shaders have been
-concatenated with the separator "---", we can load the combined shader
-as follows:
-
-~~~~
-const char shader_file[] = "shader.glsl";
-GLuint program = lglLoadGLSLProgram(shader_file);
-~~~~
-
-If the combined shader program source is defined inline as a C-string,
-we can compile the shader as follows:
-
-~~~~
-const char shader[] = "#version 120\n ...";
-...
-GLuint program = lglCompileGLSLProgram(shader);
-~~~~
-
-The shortest possible combined shader program is the following:
-
-~~~~
-#version 120
-attribute vec4 vertex_position;
-uniform mat4 mvp;
-void main()
-{
-   gl_Position = mvp * vertex_position;
-}
----
-#version 120
-uniform vec4 color;
-void main()
-{
-   gl_FragColor = color;
-}
-~~~~
-
-The above shader program is called the "plain shader". Compiling and
-activating this shader is equivalent to:
-
-~~~~
-GLuint program = lglCompileGLSLProgram(lglPlainGLSLProgram());
-...
-lglUseProgram(program);
-...
-lglDeleteGLSLProgram(program);
-~~~~
-
-If a shader contains uniform variables (besides the mandatory mv, mvp
-and mvit uniforms) we can set those uniforms via lglUniform*() for the
-currently active GLSL program. The uniforms needs to be specified after
-lglUseProgram():
-
-~~~~
-lglUseProgram(program);
-...
-lglUniformi("uniform int", 0);
-lglUniformf("uniform float", 0.0f);
-lglUniformfv("uniform vec3", vec3f(0));
-lglUniformfv("uniform vec4", vec4f(0));
-lglUniformfv("uniform mat3", mat3f(1));
-lglUniformfv("uniform mat4", mat4f(1));
-~~~~
-
-Each of the lglUniform*() functions returns an index, which can be
-used to set frequently changing uniform values directly:
-
-~~~~
-unsigned int index = lglUniform("uniform");
-lglUniform*(index, ...);
-~~~~
-
-Uniform samplers can be set with lglSampler2D/3D(), which is just a
-convenience wrapper around lglUniformi() and lglTexture2D/3D().
-
-When a different program id is passed to lglUseProgram(id), the list
-of uniforms previously registered with lglUniform*() is cleared. If it
-is necessary to keep the current list of uniforms, we may pass false
-as second parameter: lglUseProgram(id, false).
-
-----
-
-GLSL SHADER EXAMPLE /W FOGGING:
-
-In this example we use Qt to create an OpenGL core profile and a
-custom GLSL shader that implements simple exponential fogging:
-
-~~~~
-static const char vertex_shader[] =
-   "#version 120\n"
-   "attribute vec4 vertex_position;\n"
-   "attribute vec4 vertex_color;\n"
-   "uniform mat4 mvp;\n"
-   "varying vec4 frag_color;\n"
-   "vec4 fvertex() {return(mvp * vertex_position);}\n"
-   "void main()\n"
-   "{\n"
-   "   frag_color = vertex_color;\n"
-   "   gl_Position = fvertex();\n"
-   "}\n";
-
-static const char fragment_shader[] =
-   "#version 120\n"
-   "uniform float density;\n"
-   "varying vec4 frag_color;\n"
-   "void main()\n"
-   "{\n"
-   "   float w = 1.0f/gl_FragCoord.w;\n"
-   "   w = 1.0f-exp(-density*w*w);\n"
-   "   gl_FragColor = (1.0f-w)*frag_color + w*vec4(1);\n"
-   "}\n";
-
-lglVBO vbo;
-GLuint program = vbo.lglCompileGLSLProgram(vertex_shader, fragment_shader);
-vbo.lglUseProgram(program);
-vbo.lglUniformf("density", 0.1f);
-~~~~
-
-Remark: The above shader is equivalent to using lglFog(density).
-
-To compile and run the Qt example, type the following command line:
-
-&amp;gt; make qt &amp;amp;&amp;amp; ./qt_example
-
-----
-
-OBJ FORMAT EXAMPLE:
-
-The glVertex library supports the OBJ file format (as outlined in the
-Alias Wavefront OBJ file format section). In the following example we
-load the famous Utah teapot, which is actually a German Melitta
-teapot, into a VBO:
-
-~~~~
-#include &amp;lt;glvertex_objformat.h&amp;gt;
-
-...
-
-lglVBO *vbo = lglLoadObj("teapot.obj");
-if (vbo == NULL) lglFatal("file not found");
-
-...
-
-{
-   lglPushMatrixScoped();
-   lglScale(0.005);
-   vbo-&amp;gt;lglRender();
-}
-~~~~
-
-For more details, see the full source code of the Qt example in
-"examples/qt_example.cpp". The Qt example shows how to load multiple
-obj files via lglLoadObj(). It also features a track ball. The track
-ball is inherited from the "lgl_Qt_GLUI" window class, which opens a
-Qt window with an OpenGL core profile context and uses lglManip() to
-manipulate the orientation of the rendered scene depending on the
-mouse events observed.
-
-----
-
-SHARED VBO EXAMPLE:
-
-In case we want to render a particular geometric object multiple
-times, we can create a single VBO for the object and use lglModel() to
-render the object at different locations. With the "lglSharedVBO"
-container class, we can simplify the calculation of the modeling
-matrices that need to be passed to lglModel() by using the pre-model
-matrix stack:
-
-~~~~
-lglVBO *vbo = lglLoadObj("teapot.obj");
-lglSharedVBO vbos(vbo);
-
-lglMatrixMode(LGL_PREMODEL);
-for (unsigned int i=-10; i&amp;lt;=10; i++)
-{
-   lglPushMatrix();
-      lglTranslate(i,0,0);
-      if (i%2) lglRotate(90, 0,1,0);
-      vbos.push_back();
-   lglPopMatrix();
-}
-lglMatrixMode(LGL_MODELVIEW);
-
-...
-
-vbos.lglRender();
-~~~~
-
-For more details, see the full source code of the Qt pythagorean
-example in "qt_examples/qt_pythtree.cpp". This example shows how to
-create a VBO for a pythagorean tree and then renders an entire forest
-of those trees. It also demonstrates how to use Perlin noise for
-procedural texturing purposes. Hit the return key to see a single tree
-or the entire forest. To compile it on the command line type:
-
-&amp;gt; (cd qt_examples; qmake qt_pythtree.pro &amp;amp;&amp;amp; make)
-
-----
-
-REPLACEMENT SHADERS:
-
-In case we want to render multiple objects with a custom shader, that
-is consistent for all objects, we replace the default internal shader
-by a custom one:
-
-~~~~
-GLuint id = lglCompileGLSLProgram(custom_program);
-lglReplaceDefaultProgram(id);
-lglUniform("custom_uniform", custom_value);
-lglRender(vbo1);
-lglRender(vbo2);
-lglRender(vbo3);
-...
-lglDeleteGLSLProgram(id);
-~~~~
-
-Note that the internal shader is chosen depending on the set of
-attributes available in the VBO. The default attribute set includes
-normals but no color or texture coordinate attributes. As a
-consequence, the above custom shader only applies to VBOs with a
-respective attribute set. To replace a shader for a different
-attribute set, add respective boolean parameters to
-lglReplaceDefaultProgram:
-
-~~~~
-bool colors = ...;
-bool normals = ...;
-bool texcoords = ...;
-lglReplaceDefaultProgram(id, colors, normals, texcoords);
-~~~~
-
-----
-
-LIGHT SOURCES AND MATERIALS:
-
-In order to allow a more convenient specification of the lighting
-parameters, we first define and enable a light source and then define
-and enable a material, which together affect the actual Blinn-Phong
-lighting setup:
-
-~~~~
-static lgl_LightSource light;
-light.begin();
-static lgl_Material material;
-material.begin();
-lglRender(...);
-material.end();
-light.end();
-~~~~
-
-The currently active light source is used to determine the light
-vector (via setDirection resp. setPosition) and intensity (via
-setAmbientColor, setDiffuseColor, setSpecularColor), e.g. for a
-directional camera light source:
-
-~~~~
-light.setDirection(vec3f(0,0,1));
-light.setAmbientColor(vec3f(1));
-light.setDiffuseColor(vec3f(1));
-light.setSpecularColor(vec3f(1));
-~~~~
-
-A positional light source also supports constant, linear and quadratic
-attenuation coefficients (via setIntensityAttenuation), e.g. for a
-positional camera light source:
-
-~~~~
-light.setPosition(vec3f(0,0,0));
-light.setAmbientColor(vec3f(1));
-light.setDiffuseColor(vec3f(1));
-light.setSpecularColor(vec3f(1));
-light.setIntensityAttenuation(vec3f(0,0,0.001f));
-~~~~
-
-The currently active material is used to determine the material
-reflection (via setAmbientColor, setDiffuseColor, setSpecularColor,
-setSpecularExponent), e.g:
-
-~~~~
-material.setAmbientColor(vec3f(0.1f));
-material.setDiffuseColor(vec3f(0.7f));
-material.setSpecularColor(vec3f(0.2f));
-material.setSpecularExponent(30);
-~~~~
-
-----
-
-LGL SCENE GRAPH:
-
-The glVertex package contains a scene graph module that is easy to
-understand and use for OpenGL beginners. It is intended to be used for
-the construction of complex graphical objects from a set of primitive
-shapes with unit size. For this purpose it contains a base node class
-(lgl_Node) and four main scene graph node types derived from the base
-class:
-
-* lgl_GeometryNode: encapsulates geometry by means of a VBO
-  * the VBO is given as a reference to a lglVBO object
-* lgl_ContainerNode: encapsulates geometry by means of a VBO
-  * the VBO is owned by the node
-* lgl_TransformationNode: encapsulates transformations like
-  * translation, rotation and scaling
-* lgl_CameraNode: encapsulates the camera transformation
-  * accounts for both the projection and the view transformation
-
-The hierarchical construction of a scene is accomplished by adding
-child nodes to their parents via the add() method. A geometry node is
-usually a leave node of the scene graph and all the transformations
-from the root of the scene graph to the geometry node are applied to
-it in descending order.
-
-Added nodes are reference counted, so that they do not need to be
-released explicitly. They are released automatically, when the last
-referencing node is released.
-
-The add() method allows chaining, so that the addition of a geometry
-node and its transformations can be written as a single command. See
-the following example:
-
-~~~~
-#include &amp;lt;glvertex_nodes.h&amp;gt;
-
-...
-
-// vbo
-lglCube *cube = new lglCube();
-
-// camera
-lgl_CameraNode *cam = new lgl_CameraNode();
-cam-&amp;gt;setPerspective(fovy, aspect, nearp, farp);
-cam-&amp;gt;setEye(vec3(0,0,0), vec3(0,0,-1), vec3(0,1,0));
-root = new lgl_Node();
-root-&amp;gt;add(cam_);
-
-// scene
-root-&amp;gt;add(new lgl_TranslationNode(vec3(0,0,-10)))-&amp;gt;
-      add(new lgl_RotationAnimationNode(10, vec3(0,1,0))-&amp;gt;
-      add(new lgl_ScaleNode(vec3(3,1,1))-&amp;gt;
-      add(new lgl_GeometryNode(cube));
-
-root-&amp;gt;renderSceneGraph();
-~~~~
-
-List of available node types:
-
-* camera node (lgl_CameraNode)
-* geometry node (lgl_GeometryNode, lgl_ContainerNode)
-* VBO node (lgl_VBONode)
-* color node (lgl_ColorNode)
-* transformation node (lgl_TransformationNode)
- * translation node (lgl_TranslationNode)
- * rotation node (lgl_RotationNode)
- * scale node (lgl_ScaleNode)
-* texture transformation node (lgl_TextureTransformationNode)
-* animation node (lgl_AnimationNode)
- * translation animation node (lgl_TranslationAnimationNode)
- * rotation animation node (lgl_RotationAnimationNode)
-* transition node (lgl_TransitionNode)
- * translation transition node (lgl_TranslationTransitionNode)
- * rotation transition node (lgl_RotationTransitionNode)
- * scale transition node (lgl_ScaleTransitionNode)
-* warp animation node (lgl_WarpAnimationNode)
-* light node (lgl_LightNode)
-* 2D texture node (lgl_Texture2DNode)
-* 3D texture node (lgl_Texture3DNode)
-* state change node (lgl_StateNode)
- * depth write node (lgl_DepthWriteNode)
- * depth test node (lgl_DepthTestNode)
- * back-face culling node (lgl_BackFaceCullingNode)
- * blending node (lgl_BlendingNode)
- * alpha test node (lgl_AlphaTestNode)
- * fog node (lgl_FogNode)
- * line width node (lgl_LineWidthNode)
- * coloring node (lgl_ColoringNode)
- * lighting node (lgl_LightingNode)
- * texturing node (lgl_TexturingNode)
-* clipping node (lgl_ClippingNode)
-* switcher node (lgl_SwitcherNode)
-* level-of-detail node (lgl_LevelOfDetailNode)
-* subgraph node (lgl_SubgraphNode)
-* control node (lgl_ControlNode, lgl_SteerNode)
-* action node (lgl_ActionNode)
-
-The scene graph typically is created in the initializeOpenGL() method
-and rendered in the renderOpenGL() method of the Qt convenience class
-lgl_Qt_GLUI.
-
-Since the scene graph is aiming at the hierarchical construction of
-complex objects from unit shapes and not for handling an entire scene
-universe in the sense of a fully fledged game engine, it intentionally
-lacks the following features to keep the scene graph simple:
-
-* state sorting
-* bounding box culling
-* multi-pass rendering
-* support for transparency by depth sorting
-* advanced lighting and texturing techniques
-* physical simulation and collision detection
-* scene format loaders
-* picking and selection
-* etc.
-
-Nevertheless, a subset of the above features is provided by the
-following means:
-
-* The bounding box of the entire scene graph or any subgraph can be
-  determined by calling getBoundingBox() on the respective root or
-  sub-node. This method is not optimized. Calling getBoundingBox() on
-  a lgl_GeometryNode, lgl_ContainerNode or VBO is efficient, though.
-
-* View culling can be enabled for subsequent VBO rendering calls via
-  lglEnableViewCulling(), which culls the bounding box of each VBO
-  against the current view. Culling is turned off by
-  lglDisableViewCulling(). It is off by default.
-
-* Multi-pass rendering is provided via the lgl_SceneGraphScene class
-  (see below).
-
-* Picking is provided by the scene graph via pickSceneGraph() with a
-  picking ray defined in eye coordinates (see below). This method is
-  not optimized.
-
-* Transparency and selection is handled by the
-  lgl_GraphicalObjectScene class (see below).
-
-* Physical simulation is provided by the lgl_PhysicalObjects base
-  class. As a default implementation the Bullet library is wrapped in
-  the lgl_BulletObjects class (see below). Efficient picking is
-  provided via Bullet's collision system by calling
-  lgl_BulletObjects::rayTest on the scene.
-
-* Regarding scene graph optimizations, the following simple case is
-  supported: if multiple transformation nodes represent a node chain,
-  then the entire chain of transformations is merged into a single
-  transformation node containing the combined transformations. To
-  start the optimization, we call the optimizeAll() method on the root
-  node (see tutorial example "D01b_clockwork.cpp".
-
-For more details please check the following sections and the Doxygen
-documentation.
-
-----
-
-MULTI-PASS RENDERING:
-
-Multi-pass rendering is achieved by encapsulating a scene in an
-instance of a lgl_Scene class and passing this scene to an instance of
-a lgl_Renderer class.
-
-The scene class lgl_Scene
-* is an abstraction of a graphical scene
-* provides a pure virtual renderScene() method for rendering the scene
-* provides additional hooks for multi-pass rendering
-
-The scene class lgl_SceneGraphScene (derived from lgl_Scene)
-* is an abstraction of a graphical scene with a scene graph
-* provides multi-pass shadow plane rendering via setShadowPlane()
-* provides picking of objects stored as geometry nodes in the scene graph
-* provides view culling (enabled by default)
-
-The multi-pass renderer lgl_Renderer
-* is designed as an abstraction layer for multi-pass rendering
-* renders the referenced scene object multiple times
-* requires the scene object to provide hooks to setup the rendering state
-* calls the according hooks for each pass before and after the actual render call
-* provides multi-pass interlaced stereo rendering via setStereoMode()
-
-The multi-pass scene graph renderer lgl_SceneGraphRenderer (derived from lgl_Renderer)
-* is designed as a convenience wrapper for multi-pass scene graph rendering
-
-The lgl_Scene_GLUI class is a Qt convenience class based on the above
-multi-pass renderers that provides initialization and rendering hooks
-just like lgl_Qt_GLUI.
-
-If the scene supports interlaced stereo rendering, the lgl_Scene_GLUI
-convenience class understands the following command line options:
-* --stereo -&amp;gt; enable interlaced stereo rendering
-* --stereo=left -&amp;gt; enable horizontal left stereo interlacing mode
-* --stereo=right -&amp;gt; enable horizontal right stereo interlacing mode
-* --stereo=top -&amp;gt; enable vertical top stereo interlacing mode
-* --stereo=bottom -&amp;gt; enable vertical top stereo interlacing mode
-* --stereobase=... -&amp;gt; specify distance of eye points in stereo mode
-
-Please check the tutorial section for examples.
-
-----
-
-STEREO RENDERING:
-
-Stereo rendering is an example for multi-pass rendering. For the
-particular case of interlaced stereo, the LCD monitor commonly has
-alternating scan lines with different polarization. With glasses that
-show one polarization mode on the left and the other polarization mode
-on the right, two different stereo images can be provided in a single
-image. In such a setup the vertical resolution is halved.
-
-In order to generate a stereoscopic view of a particular scene, we
-need to render the scene two times. One time with one set of the scan
-lines disabled, and another time with the other set of complementary
-scan lines disabled. The eye point must match the position of the left
-resp. right eye. The distance of both is called the stereo base.
-
-With the multi-pass rendering module of glVertex this can be achieved
-easily by specifying the stereo base and the interlacing mode. Then
-the given scene is rendered automatically two times with proper scan
-line suppression and eye point displacement. For that we need to
-supply a camera object (lg_lCam) and the interlacing mode
-(lgl_interlacing_enum). The stereo base is a parameter on the camera
-(setStereoBase). The lines of sight of both eyes meet at the lookat
-point. The scene to be rendered is derived from the abstract lgl_Scene
-class by implementing the renderScene() method:
-
-~~~~
-lgl_Cam cam;
-cam.setPerspective(fovy, aspect, nearp, farp);
-cam.setEye(eye, lookat, up);
-cam.setStereoBase(base);
-
-class Scene: public lgl_Scene
-{
-public: void renderScene() {...}
-} scene;
-
-lgl_Renderer renderer;
-renderer.setScene(&amp;amp;scene);
-renderer.setStereoMode(&amp;amp;cam, LGL_INTERLACE_VERTICAL_TOP);
-~~~~
-
-Depending on the layout of the LCD's interlaced scan lines, the stereo
-mode (as given for the left eye) can be:
-
-* columns are numbered from left to right starting with 1
-* lines are numbered from top to bottom starting with 1
-* mode LGL_INTERLACE_HORIZONTAL_LEFT: odd vertical lines
-* mode LGL_INTERLACE_HORIZONTAL_RIGHT: even vertical lines
-* mode LGL_INTERLACE_VERTICAL_TOP: odd horizontal lines
-* mode LGL_INTERLACE_VERTICAL_BOTTOM: even horizontal lines
-
-For more details see the tutorial example
-"A08b_interlaced_stereo.cpp".
-
-----
-
-FBO RENDERING:
-
-Frame buffer objects (FBOs) are often used for multi-pass
-rendering. It is a common task to render a frame into a FBO in a first
-pass and to reuse the generated image as a texture in a second
-pass. The glVertex framework makes it very easy to create and use FBOs
-by providing the convenience class lglFBO:
-
-~~~~
-#include &amp;lt;glvertex_fbo.h&amp;gt;
-
-...
-
-// fbo declaration
-lglFBO fbo;
-
-...
-
-// create fbo and determine buffer size
-fbo.setupFBO(2048, 2048);
-
-...
-
-// fbo activation
-fbo.activateFBO();
-
-... render something into the fbo ...
-
-// fbo deactivation yields texture object id
-GLuint texid = fbo.deactivateFBO();
-
-... reuse fbo as texture ...
-
-~~~~
-
-Also see the tutorial example "A06_fbo.cpp".
-
-----
-
-PICKING:
-
-Picking is provided by means of a scene graph traversal. Calling
-pickSceneGraph(o, d) on the root node of a scene graph will return the
-closest VBO that is hit by a picking ray. The picking ray is defined
-by an origin o and a direction d. It is specified in eye
-coordinates. Picking is not optimized to be extremely efficient. It
-just uses a bbox test to check each VBO for intersection with the
-picking ray.
-
-Also see the tutorial example "A16_picking.cpp".
-
-----
-
-PHYSICAL SIMULATION:
-
-In order to simulate the physical behavior of moving and colliding
-objects, the lgl_BulletObjects class allows to setup a scene with
-physical objects. For this it utilizes the Bullet Physics library,
-which is auto-detected on compilation, when properly installed.
-
-Here is an example scene setup:
-
-~~~~
-lgl_BulletObjects *objects = new lgl_BulletObjects();
-objects-&amp;gt;setGravity(-9.81);
-
-lglSeed();
-for (int i=-1; i&amp;lt;=1; i++)
-   for (int j=-1; j&amp;lt;=1; j++)
-      for (int k=0; k&amp;lt;7; k++)
-      {
-         lgl_BulletCubeObject *cube = new lgl_BulletCubeObject();
-         cube-&amp;gt;setColor(vec3(1,0.75,0.5));
-         cube-&amp;gt;setPhysicalMass(10);
-         cube-&amp;gt;setPhysicalRestitution(0.25);
-         cube-&amp;gt;scale(0.5);
-         cube-&amp;gt;move(vec3(1.5*i+0.001*(lglRandom()-0.5),k+0.25,1.5*j+0.001*(lglRandom()-0.5)));
-         addObject(cube);
-         lgl_BulletSphereObject *sphere = new lgl_BulletSphereObject();
-         sphere-&amp;gt;setColor(vec3(0.5,0.75,1));
-         sphere-&amp;gt;setPhysicalMass(10);
-         sphere-&amp;gt;setPhysicalRestitution(0.9);
-         sphere-&amp;gt;scale(0.5);
-         sphere-&amp;gt;move(vec3(1.5*i+0.001*(lglRandom()-0.5),k+0.75,1.5*j+0.001*(lglRandom()-0.5)));
-         addObject(sphere);
-      }
-
-lgl_GraphicalObjectScene::setObjects(objects);
-~~~~
-
-For more information see the tutorial example "A14_physical_objects.cpp".
-
-To compile it, we need to install bullet first. On Ubuntu the
-appropriate command line is "sudo apt-get install
-libbullet-dev". Otherwise we download the bullet source distribution,
-and type the following in the unpacked source directory:
-
-&amp;gt; cmake . &amp;amp;&amp;amp; make -j8 &amp;amp;&amp;amp; sudo make install
-
-After that we compile the above example by typing the following
-command line in the tutorial directory:
-
-&amp;gt; cmake . &amp;amp;&amp;amp; make A14_physical_objects &amp;amp;&amp;amp; ./A14_physical_objects
-
-----
-
-GETTING TRANSPARENCY RIGHT:
-
-Getting transparency right is more delicate than one would think in
-the first place. In general, a scene containing one or more
-semi-transparent objects needs to be rendered with a multi-pass
-technique as follows:
-
-The geometry is seperated into two rendering bins, where the first one
-contains the fully opaque objects and the second one contains the
-semi-transparent geometry. Then the bins are rendered in strict order.
-The first bin does not require anything special, but for the second
-bin an appropriate blending function has to be enabled and depth
-writing needs to be disabled.
-
-Now it very much depends on the blending function. If the blending
-function is commutative, (e.g. in the case of multiplicative or
-additive blending), we get away with just enabling the appropriate
-blend mode via lglBlendMode(LGL_BLEND_MULT)
-resp. lglBlendMode(GL_BLEND_ADD).
-
-Unfortunately, most situations require alpha blending, which means
-that we have a non-commutative blending function enabled via
-lglBlendMode(LGL_BLEND_ALPHA). In this case, the objects need to be
-depth-sorted from back to front (so called painter's algorithm).
-
-There is one notable exception, though: If a scene only contains
-semi-transparent geometry with exactly the same color (e.g. just
-semi-transparent gray windows), then depth sorting can be omitted.
-
-For the purpose of depth sorting, the first choice is usually the MPVO
-sorting algorithm (see Peter L. Williams, "Visibility Ordering Meshed
-Polyhedra"). This algorithm computes the depth order based on the
-visibility relationships of convex object shapes. For non-convex
-objects more elaborate algorithms are necessary (see Daniel Weiskopf
-et al., "GPU-Based Interactive Visualization Techniques").
-
-Since all those algorithms come at a substantial cost, a different
-approach is chosen for use cases, where performance is more important
-than accuracy, so that an approximate depth ordering approach can be
-utilized. To compute an approximate depth order, it is sufficient to
-sort the objects based on their eye distance (aka distance-based depth
-sorting). Then the visibility ordering will be close to the ones
-computed by the more elaborated algorithms, but in some special cases
-one will be able to spot the difference, although it might not be much
-apparent. And for the case of overlapping geometry one will never get
-it right without disecting the geometry.
-
-But the ordering will get close if the objects are sphere-shaped and
-do not differ much in size. If this is not the case, objects need to
-be subdivided until their sizes match. Alternatively, the Power-Sort
-algorithm can be applied, if the geometry is strictly convex (see
-Karasick et al., "Visualization of Three-Dimensional Delaunay
-Meshes"). Also see Stefan Roettger, "Volumetric Methods for the
-Real-Time Display of Natural Gaseous Phenomena", PhD Thesis,
-University of Stuttgart, Germany, 2004.
-
-After those theoretical discussions, we get back to using the glVertex
-library: In the case of a physical object simulation as outlined in
-the previous section, the glVertex library automatically applies a
-distance-based depth sort to the semi-transparent objects in the
-second geometry bin.
-
-For more information see the tutorial example "A15_depth_sorting.cpp".
-
-----
-
-OPENGL ES:
-
-The glVertex package works with traditional desktop OpenGL as
-described in detail in the preceding sections. It also works with
-OpenGL ES, when told like so:
-
-~~~~
-#define LGL_USE_GLES
-#include &amp;lt;glvertex.h&amp;gt;
-~~~~
-
-To check out an Android OpenGL ES example, open the
-"qt_examples/qt_teapot.pro" file of the Qt teapot example with Qt
-Creator. If you installed the Android SDK and NDK properly for Qt
-Creator, you may deploy the example to your Android device and see the
-famous Utah Melitta teapot spinning around in full-screen. For more
-info on Android deployment please see the according documentation on
-the Qt developer site.
-
-Note: For OpenGL ES the GLSL shader version must be either 100, 300 or
-310 corresponding to OpenGL ES 1.0, 3.0, or 3.1. For traditional
-OpenGL the GLSL version 120 corresponds to OpenGL 2.1, version 130
-corresponds to OpenGL 3.0, 140 to 3.1, 150 to 3.2, 330 to 3.3, and so
-on...
-
-----
-
-INCLUDING GLVERTEX INTO THIRD-PARTY SOFTWARE:
-
-When using the glVertex library in third-party software, it is
-required to include the glvertex header in the module, which uses it,
-as the first include file. When using it in multiple modules, it is
-recommended to create a global singleton "GL gl" and access the
-library's functions through that singleton:
-
-~~~~
-gl.lglSomething(...);
-~~~~
-
-You can also clone the state:
-
-~~~~
-lglCloneState(gl);
-lglSomething(...);
-~~~~
-
-The easiest way to create that global singleton is to set it up as a
-reference to a static local variable in a static method like so:
-
-~~~~
-static GL *getGL()
-{
-   static GL gl;
-   return(&amp;amp;gl);
-}
-
-GL *gl = getGL();
-gl-&amp;gt;lglSomething(...);
-~~~~
-
-----
-
-QT CONVENIENCE CLASSES:
-
-The glVertex package contains several convenience classes to easily
-setup a core profile with Qt.
-
-The most important ones are the "lgl_Qt_GLWindow" and
-"lgl_Qt_GLWidget" classes. The first class creates a system window
-with a core profile (Qt5 style), the second class creates a widget
-with a core profile (Qt4 style), that can be used just like any other
-Qt widget to construct a graphical user interface. To create a window
-with a core profile, we simply include the "glvertex_qt_glwindow.h" or
-"glvertex_qt_glwidget.h" header, derive from the respective class and
-implement the following two methods:
-
-* initializeOpenGL(): called once when the OpenGL context with a core
-  profile is available. Put OpenGL state initializations here, for
-  example glClearColor(1,1,1,1), glEnable(GL_DEPTH_TEST),
-  glDisable(GL_CULL_FACE) etc.
-
-* renderOpenGL(double dt): called continuously to enable animations
-  with a certain frame rate. Put OpenGL rendering commands here, for
-  example lglBegin(), lglVertex(), lglEnd() etc. The parameter dt
-  contains the elapsed time in seconds since the last rendered
-  frame. The frame rate can be set with the setFPS() method. The
-  default is 30 frames per second.
-
-Building on the above classes, the two derived classes
-"lgl_Qt_GLWindowUI" and "lgl_Qt_GLWidgetUI" both feature a track
-ball. They also inherit the following key commands:
-
-* ESC: quit
-* Ctrl-q: quit
-* Ctrl-z: toggle Z-test
-* Ctrl-c: toggle back-face culling
-* Ctrl-b: toggle alpha blending
-* Ctrl-a: toggle A-test
-* Ctrl-w: toggle wire frame mode
-* Ctrl-0: black background
-* Ctrl-1: white background
-* Ctrl-o: toggle override
-* Ctrl-f: toggle full-screen
-* Ctrl-r: reset manipulator
-* Space: toggle animation
-
-For quickly setting up an OpenGL prototyping application, it is
-recommended to derive from the "lgl_Qt_GLUI" class. To start with an
-empty programming template just copy the "qt_template" directory and
-fill in legacy-style OpenGL commands in the renderOpenGL() method in
-"qt_template.cpp".
-
-For your convenience, the lgl_Qt_GLUI class adds diagnostic OpenGL
-output, easy key handling via the overwritable keyPressed() method,
-mouse handling via a manipulator trackball and an overwritable
-doubleClick() method. By default, a double click will toggle the wire
-frame mode and the default keyPressed() implementation will check for
-the following additional keyboard shortcuts:
-
-* Ctrl-s: save screen snapshot
-* Ctrl-t: toggle continuous screen capture
-* Ctrl-p: toggle frame rate info
-* Ctrl-k: print key info
-
-The lgl_Qt_GLUI class also provides methods for handling command line
-arguments and options in the style "--option". Any option may contain
-a "=..."  appendix. The following methods are available to handle
-command line arguments:
-
-* args() -&amp;gt; number of arguments
-* opts() -&amp;gt; number of options starting with either "-" or "--"
-* hasOption("option") -&amp;gt; check for a particular option
-* getOptionString("option") -&amp;gt; get the associated option appendix string
-* getOptionValue("option") -&amp;gt; get the associated option appendix value
-
-By default, the lgl_Qt_GLUI convenience class understands the
-following options:
-* --help -&amp;gt; show usage info
-* --fullscreen -&amp;gt; toggle fullscreen mode
-* --wireframe -&amp;gt; toggle wireframe mode
-* --pause -&amp;gt; pause animations
-
-It also understands the standard Qt command line options, for example:
-* -geometry 1024x768-0-0
-
-Derived classes like lgl_Scene_GLUI (see below) may understand more
-options. Usage details are available with the "--help" option.
-
-The following example shows how to inherit from "lgl_Qt_GLUI", render
-a single rotating directionally lit diffuse triangle and toggle
-lighting on or off when pressing the Enter key or when a mouse double
-click is encountered:
-
-~~~~
-#include &amp;lt;glvertex_qt_glui.h&amp;gt;
-
-class Qt_GLWindow: public lgl_Qt_GLUI
-{
-public:
-
-   Qt_GLWindow() : lgl_Qt_GLUI() {}
-
-protected:
-
-   void initializeOpenGL()
-   {
-      // setup OpenGL
-      glClearColor(1,1,1,1);
-      glEnable(GL_DEPTH_TEST);
-      glDisable(GL_CULL_FACE);
-
-      // disable lighting
-      lglLighting(false);
-   }
-
-   void renderOpenGL(double dt)
-   {
-      // clear frame buffer
-      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-      // projection setup
-      double fovy = 90;
-      double aspect = (double)width()/height();
-      double nearp = 0.1;
-      double farp = 10;
-      lglMatrixMode(LGL_PROJECTION);
-      lglLoadIdentity();
-      lglPerspective(fovy, aspect, nearp, farp);
-
-      // viewing setup
-      lglMatrixMode(LGL_MODELVIEW);
-      lglLoadIdentity();
-      lglLookAt(0,0,1, 0,0,0, 0,1,0);
-
-      // define local rotated coordinate system
-      static double angle=0; // rotation angle in degrees
-      static const double omega=10; // rotation speed in degrees/s
-      angle+=dt*omega;
-      lglRotate(angle, 0,1,0);
-
-      // lighting setup
-      lglLightDirection(vec3f(0,0,1), true);
-      lglLightParameters(vec3f(0), vec3f(1), vec3f(0));
-
-      // render triangle
-      lglBegin(LGL_TRIANGLES);
-         lglColor(1,0,0);
-         lglNormal(-1,-1,1);
-         lglVertex(-0.5,-0.5,0);
-         lglColor(0,1,0);
-         lglNormal(1,-1,1);
-         lglVertex(0.5,-0.5,0);
-         lglColor(0,0,1);
-         lglNormal(0,1,1);
-         lglVertex(0,0.5,0);
-      lglEnd();
-   }
-
-   void keyPressed(char key)
-   {
-      if (key == '\r')
-         lglLighting(!lglGetLighting());
-   }
-
-   void doubleClick(double x, double y)
-   {
-      keyPressed('\r');
-   }
-
-};
-
-int main(int argc, char *argv[])
-{
-   QApplication app(argc, argv);
-
-   // create OpenGL window
-   Qt_GLWindow main;
-   main.resize(640, 480);
-   main.show();
-
-   // start event loop
-   return(app.exec());
-}
-~~~~
-
-See the full source code of the above Qt example in
-"qt_examples/qt_triangle.cpp". To compile it on the command line type:
-
-&amp;gt; (cd qt_examples; qmake qt_triangle.pro &amp;amp;&amp;amp; make)
-
-Or open the .pro file with Qt Creator and hit the Run button.
-
-Note: On MacOS X you need to tell Qt Creator, where the Qt
-installation is located: Tools -&amp;gt; Options -&amp;gt; Build &amp;amp; Run -&amp;gt; Qt
-Versions -&amp;gt; Add -&amp;gt; File Browser -&amp;gt; select appropriate "qmake" -&amp;gt;
-e.g. in "/usr/local/qt.../bin/". As an alternative you may also use
-XCode. To create the corresponding XCode projects you need to run the
-"generate.sh" script from the commandline.
-
-----
-
-GLSL EDITOR:
-
-The glVertex package comes with a GLSL editor based on Qt. It allows
-basic editing of vertex and fragment GLSL programs. The editor is not
-meant for experts, it is meant for beginners to have fun writing their
-very first GLSL programs with it. To compile and run the GLSL editor,
-type the following command line:
-
-&amp;gt; make editor &amp;amp;&amp;amp; ./qt_editor
-
-For more information please read the help text of the editor.
-
-----
-
-INLINE GLSL EDITOR:
-
-We can also edit any custom shader source while the program is
-running. For that purpose, we use the QT inline editor, which shows
-the actual shader source in a separate window. The inline editor
-assumes that the shader is given as an inline "const char shader[] =
-..." C-string. The editor will load that string from the source code
-and write the modified shader back as an inline C-string when the
-program is closed.
-
-~~~~
-#include &amp;lt;glvertex_qt_shadereditor.h&amp;gt;
-
-const char shader[] = "...";
-GLuint id = lglCompileGLSLProgram(shader);
-
-create_lgl_Qt_ShaderEditor("shader", &amp;amp;id);
-
-lglUseProgram(id);
-~~~~
-
-The first parameter to the above call is the variable name of the
-shader C-string. The second parameter is a pointer to the shader id as
-returned by the OpenGL GLSL compiler.
-
-----
-
-IMAGE FILE FORMATS AND TEXTURES:
-
-The glVertex library supports the PNM and RAW image file formats.
-
-Here is an example to load a PPM image file:
-
-~~~~
-#include &amp;lt;glvertex_pnmformat.h&amp;gt;
-
-unsigned char *image;
-int width, height, components;
-
-unsigned char *image = lglReadPnmImage("example.ppm", &amp;amp;width, &amp;amp;height, &amp;amp;components);
-if (!image) lglWarning("could not load pnm image");
-~~~~
-
-In the above example the component parameter is
-* 1 for grayscale images
-* 2 for grayscale 16-bit images
-* 3 for RGB images
-* 4 for RGBA images
-
-Here is an example to load a raw image file:
-
-~~~~
-#include &amp;lt;glvertex_rawformat.h&amp;gt;
-
-unsigned char *image;
-long long width, height;
-unsigned int components;
-
-unsigned char *image = lglLoadRawImage("image.256x256_3.raw", &amp;amp;width, &amp;amp;height, &amp;amp;components);
-if (!image) lglWarning("could not load raw image");
-~~~~
-
-In the above example the file format needs to be encoded into the file name:
-* as in name.size_cellformat.raw
-* e.g. name.256x256.raw (grayscale image)
-* e.g. name.256x256_3.raw (rgb image)
-* e.g. name.256x256_u2m.raw (16-bit msb unsigned grayscale image)
-* cell format modifiers:
-*  1 = 8 bit
-*  2 = 16 bit
-*  3 = rgb
-*  4 = rgba
-*  6 = rgb 16 bit
-*  8 = rgba 16 bit
-*  u = unsigned
-*  s = signed
-*  m = msb
-*  l = lsb
-* default modifiers = u1m
-
-Here is an example to load a PNM (or RAW) image file into a texture object:
-
-~~~~
-#include &amp;lt;glvertex_texformats.h&amp;gt;
-...
-GLuint texid = lglLoadTexture("image.ppm");
-...
-lglTexture2D(texid);
-~~~~
-
-With Qt as user interface library, the glVertex library also supports
-PNG, JPEG and all other formats supported by Qt.
-
-Here is an example to load a PNG image file into a texture object:
-
-~~~~
-#include &amp;lt;glvertex_qt.h&amp;gt;
-...
-GLuint texid = lglLoadQtTexture("image.png");
-...
-lglTexture2D(texid);
-~~~~
-
-----
-
-OBJECT FILE FORMAT (ALIAS WAVEFRONT OBJ):
-
-The library supports the Alias Wavefront OBJ file format (via
-lglLoadObj and lglSaveObj). This is a simple textual format for
-indexed face sets. It essentially defines vertices ("v"), normals
-("vn") and texture coordinates ("vt") each on a single line. Then the
-geometric primitives are given each on a single line by specifiying
-the corresponding vertex, normal and texture coordinate indices of the
-faces ("f"). Here is an example, which just specifies a single
-triangle face made up from three indexed vertices:
-
-~~~~
-v -1 -0.5 0
-v 1 -0.5 0
-v 0 0.5 0
-f 1 2 3
-~~~~
-
-The same example with texture coordinates (uv-mapping):
-
-~~~~
-v -1 -0.5 0
-v 1 -0.5 0
-v 0 0.5 0
-vt 0 0
-vt 1 0
-vt 0 1
-f 1/1 2/2 3/3
-~~~~
-
-And the same example with a single normal per face:
-
-~~~~
-v -1 -0.5 0
-v 1 -0.5 0
-v 0 0.5 0
-vn 0 0 1
-f 1//1 2//1 3//1
-~~~~
-
-The official OBJ format specification allows a face to be either a
-triangle or a quad (or even a polygon). The latter is not supported by
-the glVertex OBJ format reader, so if you want to export an object
-file with blender, you need to make sure to check the "triangulate
-faces" option. The library, however, supports the inofficial extension
-of specifying per-vertex colors by appending 3 additional values to
-the vertex specification:
-
-~~~~
-v -1 -0.5 0 1 0 0
-v 1 -0.5 0 0 1 0
-v 0 0.5 0 0 0 1
-f 1 2 3
-~~~~
-
-----
-
-QT GEARS:
-
-The "Qt Gears" example is a modern version of the "glxgears" demo, which
-has been part of the Mesa library for decades. See the full source
-code of the example in "qt_examples/qt_gears.cpp". To compile it on
-the command line type:
-
-&amp;gt; (cd qt_examples; qmake qt_gears.pro &amp;amp;&amp;amp; make)
-
-----
-
-TUTORIAL:
-
-The "tutorial" folder contains many more examples with respect to the
-OpenGL pipeline, VBOs and GLSL shaders. To compile the examples type
-"cmake . &amp;amp;&amp;amp; make -j8" on the command line. For more information please
-have a look at the tutorial README.
-
-----
-
-DOXYGEN DOCUMENTATION:
-
-A detailed API and class documentation is available via Doxygen. Just
-run the following command in the top level directory:
-
-&amp;gt; make docs
-
-This will generate HTML pages with according documentation in the
-"docs/html" folder.
-
-Note: To generate the documentation, the "doxygen" and "graphviz"
-software packages need to be installed.
-
-To read the documentation open the "index.html" file with a browser
-like Firefox:
-
-&amp;gt; firefox index.html
-
-----
-
-PLATFORM NOTES:
-
-This software is mainly intended to be used with OpenGL 2.1 and higher
-(resp. OpenGL ES 2.0 and higher). For OpenGL versions 3.0 and higher
-full support for VBOs and GLSL shaders is enabled as provided by the
-respective core profile. For OpenGL versions lower than 3.0, VBOs and
-GLSL shaders are still available, but of course no functionality that
-requires a core profile. For OpenGL versions less than 2.1 the library
-will fall back to OpenGL 1.2 compatibility mode, which means that the
-legacy OpenGL 1.2 API will be used. In this case vertex arrays will be
-used instead of vertex buffers and custom shaders will be silently
-ignored.
-
-On Linux and MacOS X all recent OpenGL drivers including Intel, NVIDIA
-and ATI drivers run considerably stable with this package. Same for
-Windows and OpenGL ES on Android.
-
-On some older versions of MacOS X, however, the vertex buffer object
-implementation is seriously broken. This may result in the improper
-display of multiple vertex buffers. To my knowledge at least MacOS X
-10.5 is affected. In this case it is recommended to upgrade to a more
-recent version such as MacOS X 10.11 or later.
-
-On some Linux platforms the GCC 4.8 and 4.9 packages contain a broken
-version of the GNU dynamic linker. On Ubuntu 14.04 LTS and Open SuSe
-13.1, for example, this may result in an immediate crash when
-dynamically preloading the NVIDIA OpenGL driver. Ubuntu 16.04 LTS with
-GCC 5.2 is not affected.
-
-----
-
 Now, if you like this software, please just use it happily ever after!

 Stefan
&amp;lt;/glvertex_qt.h&amp;gt;&amp;lt;/glvertex_texformats.h&amp;gt;&amp;lt;/glvertex_rawformat.h&amp;gt;&amp;lt;/glvertex_pnmformat.h&amp;gt;&amp;lt;/glvertex_qt_shadereditor.h&amp;gt;&amp;lt;/glvertex_qt_glui.h&amp;gt;&amp;lt;/glvertex.h&amp;gt;&amp;lt;/glvertex_fbo.h&amp;gt;&amp;lt;/glvertex_nodes.h&amp;gt;&amp;lt;/glvertex_objformat.h&amp;gt;&amp;lt;/glvertex.h&amp;gt;&amp;lt;/glfw&amp;gt;&amp;lt;/glvertex.h&amp;gt;&amp;lt;/glvertex.h&amp;gt;&amp;lt;/glvertex.h&amp;gt;&amp;lt;/glslmath.h&amp;gt;&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefan Röttger</dc:creator><pubDate>Tue, 28 Jan 2020 16:09:29 -0000</pubDate><guid>https://sourceforge.neted9682fd8e55b54d8da3bd1e2135d595d84f1794</guid></item><item><title>Home modified by Stefan Röttger</title><link>https://sourceforge.net/p/glslmath/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v16
+++ v17
@@ -1,509 +1,2261 @@
-GLSLmath version 1.20 as of 28.January.2020
-----
-
-GLSLmath is free software. It is licensed under the MIT license.
-
-The code is copyright 2014-2020 by Stefan Roettger.
+glVertex version 5.0.8 as of 28.January.2020
+----
+
+The glVertex library is free software. It is licensed under
+the MIT license.
+
+The code is copyright 2015-2020 by Stefan Roettger.
 Contact: snroettg at gmail

 ----

 INTRODUCTION:

-GLSLmath consists of a single C++ header file.
-
-It allows computer graphics developers to write math operations in C++
-just like one is used to it from GLSL. This includes support for a
-complete set of operators working on vector and matrix classes,
-homogeneous coordinates and quaternions. GLSLmath also features
-testing of geometric intersections between lines, triangles and
-ellipsoids.
-
-The software is easy to install and use, so it is ideal for rapid
-prototyping or teaching purposes. Supported platforms are Unix, MacOS
-X, Windows or any C++ 98 compatible compiler. GLSLmath is mature,
-regression-tested and afaik bug-free.
+The glVertex software is a header-only C++ library.
+
+It is a convenience wrapper around OpenGL and GLSL. It also allows
+computer graphics developers to use the deprecated legacy OpenGL
+interface within a core profile. In particular it brings back the key
+concepts of the so called immediate mode.
+
+----
+
+BACKGROUND:
+
+In OpenGL 3.0 the legacy OpenGL interface was deprecated. This means
+that the so called fixed-function OpenGL pipeline was discarded in
+favor of a programmable pipeline model, which forces the use of vertex
+buffers and GLSL shaders. The main reasons behind this decision were
+rendering performance improvements, the reduction of driver complexity
+and an overall leaner OpenGL interface.
+
+As a result, the complete set of immediate mode OpenGL instructions
+like glVertex() and glColor() was removed from the OpenGL core
+profile. The immediate mode is still available in the OpenGL
+compatibility profile, but in practice this limits the computer
+graphics developer to OpenGL 2.1. If you want to use OpenGL 3.0 or
+higher, you do not have access to immediate mode any longer.
+
+The immediate mode was removed for good reasons. It allows experienced
+computer graphics developers to leverage the full power of vertex
+buffer objects and GLSL shaders. For OpenGL beginners, however, the
+already steep learning curve of OpenGL has become even steeper. What
+is more, there are still many situations, where the old legacy OpenGL
+interface would be helpful: Either for ease of implementation, rapid
+prototyping, teaching purposes or just for backwards
+compatibility. The same holds for all the use cases, where the
+limiting factor is not the vertex stage of the graphics pipeline. This
+includes volume rendering, image composing or any rasterization
+limited graphics algorithm. So there is clearly a need for legacy
+OpenGL even with modern GPUs.
+
+----
+
+GOALS:
+
+The glVertex library aims to bring back the legacy OpenGL
+fixed-function pipeline to ease the use of OpenGL core profiles. It
+tries not to provide a complete conforming implementation of the
+fixed-function pipeline, mainly for the same reasons why OpenGL 3.0
+does not support it any longer. Instead it tries to bring back the
+following key concepts of the fixed-function pipeline:
+
+* specification of vertices and attributes in immediate mode fashion
+* specification of perspective, modeling and viewing matrices in immediate mode fashion
+* matrix stack operations in immediate mode fashion
+* control over a subset of fixed-function features like
+ * blinn-phong lighting
+ * plain 2D and 3D texturing
+ * depth testing and back-face culling
+ * blending and alpha testing
+ * multiple clip planes
+ * fragment-based fog
+ * and polygon mode
+
+This does not imply that rendering performance is compromised using
+the reenabled legacy OpenGL features. The glVertex library will map
+the legacy features to the fast paths available in the OpenGL core
+profile. For example, when specifying vertices in immediate mode, the
+vertices will be automatically added to a vertex buffer object under
+the hood. As a welcome side effect, the creation of vertex buffer
+objects (VBOs) and GLSL shaders is much simplified with the glVertex
+frame work.
+
+Summing up, the glVertex software aims to be easy to install and use,
+so that it is ideal for OpenGL beginners, rapid prototyping or
+teaching purposes. At the same time it is a frame work for efficient
+OpenGL and OpenGL ES development.
+
+Supported platforms are Unix, MacOS X, Windows and Android. The single
+dependency is OpenGL (resp. OpenGL ES on mobile platforms).
+
+----
+
+REQUIREMENTS:
+
+The glVertex software depends on OpenGL. So in the following it is
+assumed that the OpenGL drivers and development libraries have been
+installed properly. Since the software is written in C++, a compiler
+such as GCC (Linux/Android), CLANG (MacOS X) or MSVC++ (Windows) is
+required also. Some of the examples given below additionally require
+GLUT, GLFW or Qt as windowing library.
+
+In order to perform an automatic installation of those dependencies
+and the glVertex library on Linux and MacOS X, please run the
+"install.sh" script from the command line:
+
+&amp;gt; ./install.sh
+
+If it finishes successfully, the instructions given below, which
+describe the manual installation of the glVertex library and its
+dependencies on the respective platforms, can be skipped.
+
+----
+
+SUPPORTED PLATFORMS AND REQUIRED PACKAGES:
+
+On Ubuntu 14.04 to 16.04 the installation command for the required packages is:
+&amp;gt; sudo apt-get install g++ cmake freeglut3-dev libglfw-dev libqt4-dev
+
+On Ubuntu 17.04 to 19.10 (resp. Debian 8) the installation command for the required packages is:
+&amp;gt; sudo apt-get install g++ cmake freeglut3-dev libglfw3-dev libqt4-dev
+
+On Linux Mint 18 the installation command for the required packages is:
+&amp;gt; sudo apt-get install g++ cmake freeglut3-dev libglfw3-dev libqt4-dev libqt4-opengl-dev
+
+On OpenSuse 11 to 15 the installation command for the required packages is:
+&amp;gt; sudo zypper install gcc-c++ cmake freeglut-devel libglfw-devel libqt4-devel
+
+On Fedora 19+ (resp. CentOs) the installation command for the required packages is:
+&amp;gt; sudo yum install gcc-c++ cmake freeglut-devel libglfw-devel libqt4-devel
+
+On Arch Linux (resp. Manjaro Linux) it is recommended to install the required packages with pacman:
+&amp;gt; sudo pacman -S gcc cmake freeglut glfw-x11 qt4
+
+On MacOS X 10.5 to 10.14 it is mandatory to install XCode first.
+Then we install the following required packages:
+&amp;gt; cmake, glfw, Qt
+
+On MacOS X 10.15 it is also required to install the XCode command line tools:
+&amp;gt; xcode-select --install
+
+For OpenGL ES development it is recommended to install Qt 5.7.1 with Android support from:
+&amp;gt; https://download.qt.io/archive/qt/5.7/5.7.1/qt-opensource-linux-x64-android-5.7.1.run
+Or we install the Qt 5.12.6 LTS release with Android support from:
+&amp;gt; https://download.qt.io/archive/qt/5.12/5.12.6/qt-opensource-linux-x64-5.12.6.run
+
+On Windows the installation is performed by downloading the CMake GUI
+and an appropriate Qt for Windows package based on MinGW:
+&amp;gt; https://download.qt.io/archive/qt/5.12/5.12.6/qt-opensource-windows-x86-5.12.6.exe
+
+Positively tested platforms are:
+* Debian 8.6
+* Ubuntu 9.10, 14.04, 16.04, 16.10, 17.04, 17.10, 18.04, 18.10, 19.04, 19.10
+* Linux Mint 18.1
+* OpenSuse 13.2, 15.1
+* MacOS X 10.5, 10.6, 10.10, 10.11, 10.12, 10.13, 10.14, 10.15
+* Android 5.0 to 7.1
+* Windows 7, 10
+
+Other platforms such as Fedora, CentOS (resp. RedHat / RHEL), Arch
+Linux (resp. Manjaro Linux) are principally supported, but those
+platforms are not tested in-depth.
+
+----
+
+INSTALLATION:
+
+The glVertex software is a C++ header-only library, so there is not
+much to do for installation purposes:
+
+To install the glVertex development headers, we simply run "sudo make
+install" in the directory of the distribution. By default the headers
+are installed in "/usr/local/include" on Linux platforms. To uninstall
+type "sudo make uninstall".
+
+The above installation procedure is equivalent to copying all headers
+(*.h) from the base distribution directory to a destination directory,
+so if you want to do a manual installation, it is as easy as this:
+
+&amp;gt; cp *.h destination/
+
+----
+
+ONLINE INSTALLER:
+
+The online installer will download the most recent glVertex package
+from the code repository and install the package with all its
+dependencies. Just download the "installer.sh" script and start it
+from the command line:
+
+&amp;gt; ./installer.sh
+
+Then the best way to start coding with the glVertex library is
+described in the quick start section. If you are interested in the
+full documentation, please read on.
+
+----
+
+USAGE PRELIMINARIES:
+
+To use the glVertex library, we need to include the "glvertex.h" C++
+header:
+
+~~~~
+ #include &amp;lt;glvertex.h&amp;gt;
+~~~~
+
+While the glVertex library restitutes parts of the legacy OpenGL 1.2
+interface, it aims not to be perfectly compatible with it. To account
+for that, all functions of the glVertex library share a "lgl"
+prefix. So instead of writing
+
+~~~~
+ glVertex3d(0,0,0); // C style
+~~~~
+
+we write
+
+~~~~
+ lglVertex(0,0,0); // C++ style
+~~~~
+
+We may also use the vector and matrix classes of the
+[GLSLmath](glslmath.md) library:
+
+~~~~
+ vec3 v(0,0,0);
+ lglVertex(v);
+~~~~

 ----

 USAGE EXAMPLE:

-To install the GLSLmath header, run "sudo make install" in the
-directory of the distribution or simply copy the header to a location
-of your choice. By default the header is installed in
-"usr/local/include" on Linux platforms.
-
-Here is a usage example that declares a position vector in homogeneous
-coordinates and then scales, rotates and translates that vector by
-multiplying it with a corresponding 4x4 matrix:
-
-~~~~
-#include &amp;lt;glslmath.h&amp;gt;
-
-vec4 v(1,0,0);
-
-std::cout &amp;lt;&amp;lt; "original vector: " &amp;lt;&amp;lt; v &amp;lt;&amp;lt; std::endl;
-
-mat4 S = mat4::scale(3);
-mat4 R = mat4::rotate(90, vec3(0,1,0));
-mat4 T = mat4::translate(vec3(1,0,-10));
-mat4 M = T*R*S;
-
-v = M*v; // yields (1,0,-13)
-
-std::cout &amp;lt;&amp;lt; "transformed vector: " &amp;lt;&amp;lt; v &amp;lt;&amp;lt; std::endl;
-~~~~
-
-Note: GLSLmath has been inspired by the glm and slmath libraries,
-which aim to mimic GLSL, as well. In contrast to those, GLSLmath does
-not focus on a complete conforming implementation of GLSL. It rather
-aims to provide a convenient single header file that implements the
-most commonly used subset of linear algebra operations of GLSL so that
-it is easy to use for rapid prototyping and GLSL teaching purposes.
-
-----
-
-API DOCUMENTATION:
-
-* Creating a 3D vector:
-
-~~~~
-  vec3 v(0,0,-10);
-~~~~
-
-* Accessing the components of a 3D vector:
-
-~~~~
-  double x = v.x;
-  double y = v.y;
-  double z = v.z;
-~~~~
-
-* Printing a 3D vector:
-
-~~~~
-  std::cout &amp;lt;&amp;lt; "v = " &amp;lt;&amp;lt; v &amp;lt;&amp;lt; std::endl;
-   yields
-  "v = (0, 0, -10)"
-~~~~
-
-* Getting the length and norm of a vector:
-
-~~~~
-  vec3 v(0,3,4);
-  double l = v.length(); // yields 5
-  double l2 = v.norm(); // yields 25
-~~~~
-
-* Averaging two vectors p1 and p2:
-
-~~~~
-  vec3 p1(-10,0,0), p2(10,0,0);
-  vec3 v = 0.5*(p1+p2); // yields (0,0,0)
-~~~~
-
-* Linear interpolation of two vectors p1 and p2:
-
-  Let w be the linear interpolation factor in the range [0..1]:
-
-~~~~
-  vec3 p1(-10,0,0), p2(10,0,0);
-
-  double w = 0.5;
-  vec3 v = (1-w)*p1 + w*p2; // yields (0,0,0)
-~~~~
-
-* Calculating the dot product:
-
-~~~~
-  vec3 a(1,0,0), b(0,0,1);
-  double d = a.dot(b); // yields 0
-~~~~
-
-* Calculating the cross product:
-
-~~~~
-  vec3 a(1,0,0), b(0,0,1);
-  vec3 c = a.cross(b); // yields (0,-1,0)
-~~~~
-
-* Computing a normalized direction vector from two position vectors:
-
-~~~~
-  vec4 p1(0,20,0), p2(0,10,0);
-  vec4 d = (p2-p1).normalize(); // yields (0,-1,0)
-~~~~
-
-  Note that p1 and p2 are position vectors with homogeneous coordinate
-  w=1 and d is a direction vector with homogeneous coordinate w=0!
-
-* Component swizzeling:
-
-~~~~
-  vec4 a(1,2,3,4);
-  vec4 b(a.wzyx());      // yields (4,3,2,1)
-  vec4 c(b.zw(),b.xy()); // yields (2,1,4,3)
-~~~~
-
-* Calculating a normalized triangle normal from the three corners a,b,c:
-
-~~~~
-  vec3 normal = vec3::normal(a,b,c);
-~~~~
-
-* Calculating the area of a triangle with the three vertices a,b,c:
-
-~~~~
-  double area = vec3::area(a,b,c);
-~~~~
-
-* Computing the diffuse lighting term:
-
-  Let d be the direction vector of a light source and v1/v2/v3 the
-  three vertices of a triangle, then the diffuse lighting term is
-  calculated as follows:
-
-~~~~
-  vec3 n = (v2-v1).cross(v3-v1).normalize();
-  double term = fabs(d.dot(n));
-~~~~
-
-* Reflecting a light vector at a surface normal:
-
-  Let v be the incident light vector, let n be the normalized surface
-  normal pointing outwards, then the reflected vector r is computed as
-  follows:
-
-~~~~
-  vec3 v(1,-1,0);
-  vec3 n(0,1,0);
-
-  vec3 r = v.reflect(n); // yields (1,1,0)
-~~~~
-
-* Accessing the components of a color vector:
-
-~~~~
-  vec4 color(1,0,0);  // opaque red
-  double r = color.r; // r=1
-  double g = color.g; // g=0
-  double b = color.b; // b=0
-  double a = color.a; // a=1
-~~~~
-
-* Blending two colors:
-
-~~~~
-  vec4 color1(1,0,0);
-  vec4 color2(0,0,1, 0.25);
-  vec4 mix = color1.blend(color2); // yields (0.75,0,0.25,1)
-~~~~
-
-* Procedural-style vector operations:
-
-  length of a vector v: length(v)
-  dot product of two vectors a and b: dot(a, b) 
-  cross product of two vectors a and b: cross(a, b)
-  norm of a vector v: norm(v)
-  normalization of a vector v: normalize(v)
-  reflection of a vector v at a surface normal n: reflect(v, n);
-  linear interpolation of two vectors a and b with factor w: lerp(w, a, b)
-  blending two colors a and b: blend(a, b)
-
-* Creating a 3x3 identity matrix:
-
-~~~~
-  mat3 I;
-   or
-  mat3 M(1);
-~~~~
-
-* Printing a 3x3 matrix:
-
-~~~~
-  std::cout &amp;lt;&amp;lt; "I = " &amp;lt;&amp;lt; I &amp;lt;&amp;lt; std::endl;
-   yields
-  "I = ((1, 0, 0), (0, 1, 0), (0, 0, 1))"
-~~~~
-
-* Creating a 3x3 diagonal matrix:
-
-~~~~
-  mat3 D(vec3(1,2,3));
-~~~~
-
-* Getting the determinant of a 3x3 matrix:
-
-~~~~
-  double d = D.det();
-~~~~
-
-* Creating a 3x3 matrix from three row vectors and multiplying it with a vector:
-
-~~~~
-  mat3 M(vec3(0,1,0),
-         vec3(-1,0,0),
-         vec3(0,0,1));
-
-  vec3 v(-10,0,0);
-  v = M*v; // yields (0,10,0)
-~~~~
-
-* Pretty-printing a 3x3 matrix:
-
-~~~~
-  glslmath::print(M, "M");
-
-  prints:
-
-      /       0             1             0       \
-  M = |      -1             0             0       |
-      \       0             0             1       /
-~~~~
-
-* Creating a 3x3 matrix from three column resp. row vectors:
-
-~~~~
-  mat3 Mc = mat3::columns(vec3(a,b,c), vec3(d,e,f), vec3(g,h,i));
-  mat3 Mr = mat3::rows(a,b,c, d,e,f, g,h,i);
-~~~~
-
-* Creating an affine 4x4 matrix and multiplying it with a position vector:
-
-  The matrix transforms homogeneous points from the local coordinate
-  system to a coordinate system with the origin o and the coordinate
-  axis x, y and z:
-
-~~~~
-  vec3 o = vec3(3,3,3);
-  vec3 x = vec3(0,1,0);
-  vec3 y = vec3(0,0,1);
-  vec3 z = vec3(1,0,0);
-  mat4 T = mat4::transform(o,x,y,z);
-
-  vec4 v(1,0,0);
-  v = T*v; // yields (3,4,3,1)
-~~~~
-
-* Available 4x4 matrix transformations as defined by the OpenGL standard:
-
-  translation by a vector v: mat4::translate(v)
-  rotation about an axis a and an angle of d degrees: mat4::rotate(d, a)
-  scaling with a factor f: mat4::scale(f)
-
-* Procedural-style 4x4 matrix transformations:
-
-  translation by a vector v: translate(M, v)
-  rotation about an axis a and an angle of d degrees: rotate(M, d, a)
-  scaling with a factor f: scale(M, f)
-
-  The above procedures multiply the corresponding transformation
-  matrix onto a given matrix M (from the right-hand side).
-
-* Using mat4 for MVP calculations as defined by the OpenGL
-  standard. The resulting matrix is transferred with glUniform:
-
-~~~~
-  mat4 P = mat4::perspective(90,1,1,100);
-  mat4 V = mat4::lookat(vec3(0,3,10), vec3(0,0,0), vec3(0,1,0));
-  mat4 M = mat4::translate(0,0,-10) * mat4::rotate(90, vec3(0,1,0)) * mat4::scale(3);
-
-  mat4 MVP = P*V*M;
-
-  glUniformMatrix4fv(location, 1, GL_FALSE, (const float *)mat4f(MVP));
-~~~~
-
-  Note that the order of matrix multiplications is the reverse of the
-  logical order of the applied transformations.
-
-  Also note that linear math calculations are done with double
-  precision to avoid numerical instabilities, but the transfer of the
-  final matrix to the gpu is done with single precision float
-  accuracy!
-
-* By default, matrices are multiplied from the right-hand side, e.g.:
-
-~~~~
-  mat4 M = mat4::translate(0,0,-10);
-  M *= mat4::rotate(90, vec3(0,1,0)); // M = T*R
-~~~~
-
-  But matrices can also be multiplied from the left hand-side to
-  reverse the order of transformations:
-
-~~~~
-  mat4 M = mat4::translate(0,0,-10);
-  M &amp;lt;&amp;lt;= mat4::rotate(90, vec3(0,1,0)); // M = R*T
-~~~~
-
-* Calculating the inverse transpose of the MVP matrix (used for normal transformations):
-
-~~~~
-  mat4 M = MVP.invert().transpose();
-~~~~
-
-* Special matrices:
-
-The following matrices are supported as defined by the OpenGL standard:
-
-~~~~
-   // create orthographic projection matrix
-   mat4 Mo = mat4:ortho(left, right, bottom, top, near, far);
-
-   // create frustum projection matrix
-   mat4 Mf = mat4:frustum(left, right, bottom, top, near, far);
-~~~~
-
-For convenience, the following matrices can be constructed as well:
-
-~~~~
-   // create affine transformation matrix consisting of
-   // a rotation resp. non-singular matrix M and a translation vector v
-   mat4 Mt = mat4:transform(M, v);
-
-   // create parallel projection matrix defined by
-   // a plane point p and normal n and a projection direction vector v
-   mat4 Mp = mat4:parallel(p, n, d);
-~~~~
-
-* Procedural-style matrix operations:
-
-  determinant of a matrix M: determinant(M)
-  transposition of a matrix M: transpose(M)
-  inversion of a matrix M: inverse(M)
-
-* Hierarchical modeling with the scoped matrix stack:
-
-  Given the following scene graph with
-
-~~~~
-  + = root node
-  C = camera
-  T0-T2 = modeling transformations
-  G = geometry node
-
-        +
-       / \
-      /   \
-     T0    \
-      |     C
-      |
-      |
-     / \
-    /   \
-   T1   T2
-    \   /
-     \ /
-      |
-      |
-      |
-      G
-~~~~
-
-  Then the matrices needed to render the two instances of the geometry
-  node can be computed with the scoped matrix stack of GLSLmath:
-
-~~~~
-  mat4 V = mat4::lookat(C, ...);
-  mat4 P = mat4::perspective(...);
-
-  load_matrix(P*V);
-  {
-     mult_matrix_scoped(T0);
-     {
-        mult_matrix_scoped(T1);
-        glUniformMatrix4fv(location, 1, GL_FALSE, (const float *)mat4f(top_matrix()));
-        render(G);
-     }
-     {
-        mult_matrix_scoped(T2);
-        glUniformMatrix4fv(location, 1, GL_FALSE, (const float *)mat4f(top_matrix()));
-        render(G);
-     }
-  }
-~~~~
-
-* Hierarchical modeling with the OpenGL matrix stack:
-
-  Given a scene where a glPushMatrix/glPopMatrix pair is required:
-
-~~~~
-   glPushMatrix();
-   ...
-   glPopMatrix();
-~~~~
-
-  The above pair can be rewritten with the OpenGL scoped matrix stack:
-
-~~~~
+Here is a usage example that renders a single triangle in immediate
+mode. Under the hood, the immediate mode calls are translated to the
+creation of according vertex buffers (VBOs) and GLSL shaders, which
+simulate the fixed functionality of the legacy OpenGL 1.2 interface:
+
+~~~~
+#include &amp;lt;glvertex.h&amp;gt;
+
+...
+
+// matrix setup
+lglMatrixMode(LGL_PROJECTION);
+lglLoadIdentity();
+lglPerspective(fovy, aspect, nearp, farp);
+lglMatrixMode(LGL_MODELVIEW);
+lglLoadIdentity();
+lglLookAt(0,0,1, 0,0,0, 0,1,0);
+
+// render triangle
+lglBegin(LGL_TRIANGLES);
+   lglColor(1,0,0);
+   lglVertex(-0.5,-0.5,0);
+   lglColor(0,1,0);
+   lglVertex(0.5,-0.5,0);
+   lglColor(0,0,1);
+   lglVertex(0,0.5,0);
+lglEnd();
+~~~~
+
+The above example is available with GLUT as windowing library. It does
+not yet use a core rendering profile. This is achieved with GLFW and
+Qt further below. To compile and run the GLUT example on the Unix or
+Mac command line type:
+
+&amp;gt; make glut &amp;amp;&amp;amp; ./glut_example
+
+Or use CMake to compile and run it on the Unix or Mac command line:
+
+&amp;gt; (cd examples; cmake . &amp;amp;&amp;amp; make &amp;amp;&amp;amp; ./glut_example)
+
+On Windows use the CMake GUI to create a VC++ project.
+
+----
+
+GLSLMATH USAGE:
+
+Internally, the glVertex package uses the GLSLmath library to perform
+linear math calculations such as the calculation of projection and
+viewing matrices.
+
+For example, the legacy-style matrix setup used in the previous
+example is equivalent to the following linear math calculations using
+[GLSLmath](glslmath.md):
+
+~~~~
+// look at world origin (0,0,0) from (0,0,2) with up being (0,1,0)
+mat4 MV = mat4::lookat(vec3(0,0,2), vec3(0,0,0), vec3(0,1,0));
+// camera perspective defining field-of-view etc.
+mat4 P = mat4::perspective(fovy, aspect, nearp, farp);
+
+// mvp matrix setup
+mat4 MVP = P * MV;
+lglLoadMatrix(MVP);
+~~~~
+
+----
+
+GLVERTEX QUICK START:
+
+If you cannot wait to get your hands on the glVertex frame work and
+write your own 3D graphics code, the Qt programming template in the
+"qt_template" directory is the best way to get started. The template
+"qt_template.cpp" just shows an empty window, which is waiting for you
+to fill in legacy-style OpenGL code in the marked section of the
+renderOpenGL() method. But before doing so, please run the installer
+by typing "./installer.sh" to make sure that the frame work has been
+installed properly. See also the quickstart sheet ("QUICKSTART.txt").
+
+As a starting point, it is recommended to uncomment the code that is
+provided in the marked section as a legacy-style programming
+example. This is achieved by opening the "qt_template.pro" file with
+Qt Creator. Then we apply the code changes in the editor pane and hit
+the green Run button to compile an start the modified program. At your
+option you may also type "cmake . &amp;amp;&amp;amp; make" to compile the example with
+CMake on the command line. Or type "qmake &amp;amp;&amp;amp; make" on the command line
+to compile with QMake.
+
+For a quick overview of the programming API, see the glVertex quick
+reference sheet ("QUICKREF.txt") and the GLSLmath documentation
+("glslmath.txt"). Or have a look at the code examples in the
+"qt_examples" directory.
+
+More details on the Qt framework used in the programming template are
+given in the section about "Qt Convenience Classes" further below. For
+now we concentrate on creating a core profile by using another
+graphics framework: GLFW.
+
+----
+
+OPENGL CORE PROFILE EXAMPLE:
+
+The following example renders a single triangle using an OpenGL core
+profile. We are using the GLFW library to create an OpenGL 3.2 core
+profile. The example is based on the "simple.c" example of GLFW with
+the following modifications: hints for GLFW were added to create an
+according core profile and the immediate mode gl calls were replaced
+with according lgl calls.
+
+~~~~
+#include &amp;lt;glvertex.h&amp;gt;
+
+#include &amp;lt;glfw glfw3.h=""&amp;gt;
+
+int main(void)
+{
+   GLFWwindow* window;
+
+   if (!glfwInit())
+      exit(EXIT_FAILURE);
+
+   glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+   glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
+   glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
+   glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+
+   window = glfwCreateWindow(640, 480, "glVertex GLFW Example", NULL, NULL);
+
+   glfwMakeContextCurrent(window);
+   glfwSwapInterval(1);
+
+   while (!glfwWindowShouldClose(window))
    {
-      glPushMatrixScoped();
-      ...
+      int width, height;
+
+      glfwGetFramebufferSize(window, &amp;amp;width, &amp;amp;height);
+
+      double fovy = 90;
+      double aspect = (double)width/height;
+      double nearp = 0.1;
+      double farp = 10;
+
+      // clear frame buffer
+      glViewport(0, 0, width, height);
+      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+      glEnable(GL_DEPTH_TEST);
+      glDisble(GL_CULL_FACE);
+
+      // matrix setup
+      lglMatrixMode(LGL_PROJECTION);
+      lglLoadIdentity();
+      lglPerspective(fovy, aspect, nearp, farp);
+      lglMatrixMode(LGL_MODELVIEW);
+      lglLoadIdentity();
+      lglLookAt(0,0,1, 0,0,0, 0,1,0);
+
+      // render triangle
+      lglBegin(LGL_TRIANGLES);
+         lglColor(1,0,0);
+         lglVertex(-0.5,-0.5,0);
+         lglColor(0,1,0);
+         lglVertex(0.5,-0.5,0);
+         lglColor(0,0,1);
+         lglVertex(0,0.5,0);
+      lglEnd();
+
+      // swap frame buffer
+      glfwSwapBuffers(window);
+      glfwPollEvents();
    }
-~~~~
-
-* Quaternions:
-
-  Transformation of a vector by two consecutive rotations represented
-  as quaternions:
-
-~~~~
-  quat a = quat::rotate(10, vec3(0,1,0));
-  quat b = quat::rotate(80, vec3(0,1,0));
-  quat q = a*b;
-
-  vec3 v(1,0,0);
-  v = q*v; // yields (0,0,1)
-~~~~
-
-* HSV to RGB conversion:
-
-~~~~
-  vec3 rgb1 = glslmath::hsv2rgb(0,1,1); // red
-  vec3 rgb2 = glslmath::hsv2rgb(60,1,1); // yellow
-  vec3 rgb3 = glslmath::hsv2rgb(120,1,0.25); // dark green
-  vec3 rgb4 = glslmath::hsv2rgb(240,0.5,1); // blueish
-~~~~
-
-* 3D Perlin noise:
-
-~~~~
-  vec3 coord(0.5,0.5,0.5);
-  double noise_value = glslnoise::noise(coord);
-  vec3 noise_vector = glslnoise::noise3D(coord);
-~~~~
-
-* Ray/plane intersection testing:
-
-  Let p be the start point and d be the direction vector of a half ray
-  (denoted by [p-&amp;gt;d]). Then the distance l to a plane defined by a
-  point o on the plane and the plane normal n is:
-
-~~~~
-   vec3 p(0,0,0), d(1,1,1); // ray definition
-   vec3 o(1,0,0), n(1,0,0); // plane definition
-
-   double l = glslmath::intersect_ray_plane(p,d.normalize(), o,n); // signed euclidean distance
-
-   if (l!=DBL_MAX) // plane is not parallel to half ray
-      if (l&amp;gt;=0) // half ray hits plane in the right direction
+
+   glfwDestroyWindow(window);
+
+   glfwTerminate();
+   exit(EXIT_SUCCESS);
+}
+~~~~
+
+To compile and run the GLFW example on the command line type:
+
+&amp;gt; make glfw &amp;amp;&amp;amp; ./glfw_example
+
+----
+
+VBO USAGE EXAMPLE:
+
+Besides simulating the fixed function pipeline, the glVertex library
+is also handy for creating VBOs in the style of the legacy interface:
+
+~~~~
+#include &amp;lt;glvertex.h&amp;gt;
+
+...
+
+// declare vbo
+lglVBO vbo;
+
+...
+
+// compile vbo
+vbo.lglBegin(LGL_TRIANGLES);
+   vbo.lglColor(1,0,0);
+   vbo.lglVertex(-0.5,-0.5,0);
+   vbo.lglColor(0,1,0);
+   vbo.lglVertex(0.5,-0.5,0);
+   vbo.lglColor(0,0,1);
+   vbo.lglVertex(0,0.5,0);
+vbo.lglEnd();
+
+...
+
+// render vbo instance at position a
+lglPushMatrix();
+lglTranslate(a);
+vbo.lglRender();
+lglPopMatrix();
+
+// render vbo instance at position b
+lglPushMatrix();
+lglTranslate(b);
+vbo.lglRender();
+lglPopMatrix();
+~~~~
+
+Using the scoped matrix stack of glVertex, the above matrix operations
+can be rewritten as follows:
+
+~~~~
+{
+   // render vbo instance at position a
+   lglPushMatrixScoped();
+   lglTranslate(a);
+   vbo.lglRender();
+}
+
+{
+   // render vbo instance at position b
+   lglPushMatrixScoped();
+   lglTranslate(b);
+   vbo.lglRender();
+}
+~~~~
+
+The compiled vertices are stored in the VBO with double precision by
+default. The attributes are stored with float precision. For OpenGL ES
+the precision is float for both.
+
+In order to use only float precision for the compiled vertices, we use
+the lglVBOf class instead of lglVBO.
+
+----
+
+PRE-DEFINED VBOS:
+
+For convenience, the following geometric objects are available as
+predefined VBOs (meaning that they are derived from lglVBO as base class):
+
+* lglCube: unit cube
+* lglWireCube: unit wireframe cube
+* lglBox: rectangular box
+* lglTet: unit tetrahedron
+* lglPyramid: unit pyramid
+* lglPyramidBase: unit pyramid base
+* lglPrism: slanted unit prism
+* lglSphere: unit sphere
+* lglHemisphere: unit hemisphere
+* lglCylinder: unit cylinder
+* lglHemiCylinder: unit hemi-cylinder
+* lglDisc: unit disc
+* lglHemiDisc: unit hemi-disc
+* lglCone: unit cone
+* lglConeBase: unit cone base
+* lglRing: ring geometry
+* lglArc: arc geometry
+* lglTorus: unit torus
+* lglHemiTorus: unit hemi-torus
+* lglObj: pre-loaded geometry from an OBJ file
+* lglTeapot: the Melitta resp. Utah teapot
+* lglCoordSys: colored unit coordinate system axis
+
+The above predefined vertex buffer objects (except the predefined
+coordinate system axis) do not contain color attributes but outward
+facing normals and texture coordinates, so that they can be textured
+and shaded using ambient, diffuse and specular Blinn-Phong
+lighting. By default the light is a white directional light source
+positioned at the eye point. This means that the objects appear to be
+lit by a white head light.
+
+----
+
+PRE-DEFINED VBO EXAMPLE:
+
+As an example for pre-defined VBOs, the following code snippet renders
+a red shaded unit sphere at position p:
+
+~~~~
+// instantiate predefined sphere vbo
+lglSphere sphere;
+
+...
+
+{
+   // render red sphere instance at position p
+   lglPushMatrixScoped();
+   lglTranslate(p);
+   lglColor(1,0,0);
+   sphere.lglRender();
+}
+~~~~
+
+The usage of VBOs as shown above is demonstrated in the VBO
+example. To compile and run the example on the command line type:
+
+&amp;gt; make vbo &amp;amp;&amp;amp; ./vbo_example
+
+----
+
+TRIANGLE STRIPPING EXAMPLE:
+
+In case we want to compile a couple of triangle or quad strips into a
+VBO, we need to use a trick to combine the strips into a single
+VBO. The trick employed by the glVertex library is to add degenerate
+triangles between the strips so that they form a single batch. As a
+nice side effect, this is also the fastest rendering option to my
+knowledge (depending on the particular GPU hardware, ram and drivers
+there might be faster rendering options, but this cannot be
+generalized without a-priori knowledge of the actual rendering
+setup). Here is an example:
+
+~~~~
+lglVBO vbo;
+
+vbo.lglBegin(LGL_TRIANGLE_STRIP);
+   vbo.lglVertex(0,0,0);
+   vbo.lglVertex(0,1,0);
+   vbo.lglVertex(1,0,0);
+   vbo.lglVertex(1,1,0);
+   vbo.lglVertex(2,0,0);
+   vbo.lglVertex(2,1,0);
+vbo.lglEnd();
+vbo.lglBegin(LGL_TRIANGLE_STRIP);
+   vbo.lglVertex(0,1,0);
+   vbo.lglVertex(0,2,0);
+   vbo.lglVertex(1,1,0);
+   vbo.lglVertex(1,2,0);
+   vbo.lglVertex(2,1,0);
+   vbo.lglVertex(2,2,0);
+vbo.lglEnd();
+~~~~
+
+In between the two strips, the glVertex library automatically inserts
+the two vertices
+~~~~
+   vbo.lglVertex(2,1,0);
+   vbo.lglVertex(0,1,0);
+~~~~
+so that the two strips are effectively identical to the following
+single strip:
+~~~~
+vbo.lglBegin(LGL_TRIANGLE_STRIP);
+   vbo.lglVertex(0,0,0);
+   vbo.lglVertex(0,1,0);
+   vbo.lglVertex(1,0,0);
+   vbo.lglVertex(1,1,0);
+   vbo.lglVertex(2,0,0);
+   vbo.lglVertex(2,1,0);
+   vbo.lglVertex(2,1,0);
+   vbo.lglVertex(0,1,0);
+   vbo.lglVertex(0,1,0);
+   vbo.lglVertex(0,2,0);
+   vbo.lglVertex(1,1,0);
+   vbo.lglVertex(1,2,0);
+   vbo.lglVertex(2,1,0);
+   vbo.lglVertex(2,2,0);
+vbo.lglEnd();
+~~~~
+
+In the latter case, two degenerate triangles were created
+additionally. These are detected and discarded automatically by the
+graphics hardware. As a result, the triangle strip appears to be
+restarting in the middle. Even though we are generating two more
+triangles, the single strip can be rendered faster by the GPU, because
+it does not require another render call on the CPU side to start the
+next strip explicitly.
+
+The above principle is demonstrated in the mesh example. It constructs
+a triangle mesh from multiple triangle strips. To compile and run the
+example on the command line type:
+
+&amp;gt; make mesh &amp;amp;&amp;amp; ./mesh_example
+
+----
+
+PROGRAMMING API:
+
+In accordance with the legacy OpenGL 1.2 specification, the glVertex
+library supports the following API functions:
+* lglBegin, lglEnd
+* lglVertex, lglColor, lglNormal, lglTexCoord
+* lglMatrixMode, lglLoadIdentity, lglLoadMatrix, lglMultMatrix
+* lglScale, lglTranslate, lglRotate
+* lglOrtho, lglFrustum, lglPerspective, lglLookAt
+* lglPushMatrix, lglPopMatrix
+* lglViewport
+* lglClearColor, lglClear
+* lglLight
+* lglClipPlane
+* lglFog
+* lglLineWidth
+* lglPolygonMode
+* lglGetError
+
+Additionally, it supports the following extended convenience functions:
+* lglGetGLVersion, lglGetGLSLVersion
+* lglGetRenderer, lglGetVendor, lglGetVendorName
+* lglGetColor
+* lglAttribute
+* lglGetMatrixMode, lglGetMatrix
+* lglGetProjectionMatrix, lglGetModelViewMatrix, lglGetTextureMatrix
+* lglGetInverseModelViewMatrix, lglGetInverseTransposeModelViewMatrix
+* lglGetModelViewProjectionMatrix
+* lglRotateX, lglRotateY, lglRotateZ
+* lglParallel
+* lglProjection, lglModelView, lglView, lglTexture
+* lglManip, lglResetManip, lglIsManipApplied
+* lglGetManip, lglGetInverseTransposeManip
+* lglModel, lglGetModelMatrix, lglGetInverseTransposeModelMatrix
+* lglTex, lglGetTexMatrix
+* lglReadFile, lglReadTextFile
+* lglReadPnmImage, lglWritePnmImage
+* lglReadRawImage, lglWriteRawImage
+* lglSupportsGLSL, lglGetGLSLVersionString
+* lglCompileGLSLVertexShader, lglCompileGLSLFragmentShader, lglDeleteShader
+* lglCombineGLSLProgram, lglSplitGLSLProgram
+* lglCompileGLSLProgram, lglLinkGLSLProgram, lglDeleteGLSLProgram
+* lglLoadGLSLProgram, lglPlainGLSLProgram
+* lglUseProgram, lglReuseProgram, lglUseDefaultProgram
+* lglGetProgram, lglGetActiveProgram
+* lglUniform, lglUniformi, lglUniformf, lglUniformfv
+* lglSampler, lglSampler2D, lglSampler3D
+* lglLightDirection, lglLightPosition
+* lglLightVector, lglGetLightVector
+* lglLightParameters, lglGetLightParameters
+* lglLightSourceParameters, lglGetLightSourceParameters
+* lglMaterialParameters, lglGetMaterialParameters
+* lglTexture2D, lglGetTexture2D
+* lglTexture3D, lglGetTexture3D
+* lglCreateTexmap2D, lglCreateMipmap2D
+* lglCreateTexmap3D, lglCreateNoiseTexmap3D
+* lglDeleteTexmap
+* lglTexCoordGen, lglGetTexCoordGen
+* lglTexMagFilter2D, lglTexWrap2D, lglTexFilterAnisotropic2D
+* lglTexMagFilter3D, lglTexWrap3D, lglTexFilterAnisotropic3D
+* lglLoadTexture, lglLoadQtTexture
+* lglLoadObj, lglSaveObj
+* lglColoring, lglLighting, lglTexturing
+* lglGetColoring, lglGetLighting, lglGetTexturing
+* lglCloneUniforms, lglCopyUniforms
+* lglCloneProgram, lglCopyProgram
+* lglCloneState
+* lglInitializeOpenGL
+* lglRGBAWrite, lglGetRGBAWrite
+* lglZWrite, lglGetZWrite
+* lglDepthTest, lglGetDepthTest
+* lglBackFaceCulling, lglGetBackFaceCulling
+* lglBlendMode, lglGetBlending, lglGetBlendMode
+* lglAlphaTest, lglGetAlphaTest, lglGetAlphaTestValue
+* lglGetAlphaTestGreater, lglGetAlphaTestEqual
+* lglGetClipPlane, lglGetClipPlaneEquation
+* lglGetFog, lglGetFogDensity, lglGetFogColor
+* lglGetLineWidth
+* lglTogglePolygonMode, lglGetPolygonMode
+* lglInterlacingMode, lglComplementaryInterlacingMode, lglGetInterlacingMode
+* lglReadRGBPixels
+* lglBeginRayCast, lglRayCast, lglEndRayCast, lglGetRayCastDistance
+* lglEnableViewCulling, lglDisableViewCulling
+* lglRandom, lglSeed
+* lglWarning, lglError, lglFatal
+* lglVerbosity
+
+Additionally, the VBO classes support the following methods:
+* lglGetVertexMode, lglGetVertexCount
+* lglGetBoundingBox, lglGetCenter, lglGetExtent
+* lglGetBoundingSphere, lglGetRadius, lglGetNorm
+* lglGetMaxExtent, lglGetMaxAbsCoord
+* lglRender
+
+The following VBO classes are provided:
+* lglVBO (base class)
+* lglVBOf (uses float instead of double for storing vertices)
+* lglSharedVBO (multiple shared instances with transformation matrices)
+* lglCube, lglWireCube, lglBox, lglTet, lglPyramid, lglPyramidBase, lglPrism
+* lglSphere, lglHemisphere, lglCylinder, lglHemiCylinder
+* lglDisc, lglHemiDisc, lglCone, lglConeBase, lglRing, lglArc
+* lglTorus, lglHemiTorus
+* lglSheet, lglSheetBezier, lglSheetDisc
+* lglShim, lglSpiral, lglGear
+* lglFunctional, lglRotational, lglRotationalBezier
+* lglCylindrical, lglSpherical, lglToroidal
+* lglExtrusion, lglExtrusionBezier, lglReplicatedGeometry
+* lglPlanar, lglPlanarBezier
+* lglObj, lglTeapot
+* lglCoordSys
+
+Note: The lglLoadObj method and the lglObj and lglTeapot classes load
+OBJ data from /usr/local/share, if no data is present in the current
+working directory.
+
+----
+
+DETAILED API DESCRIPTION:
+
+The basic behavior of the glVertex API is closely related to the
+immediate mode and the fixed function pipeline of legacy OpenGL:
+
+* All legacy OpenGL modeling transformations like glTranslate(),
+  glRotate() and glScale() work as usual (except for using the "lgl"
+  instead of the "gl" prefix).
+
+* The same holds for matrix mode operations via lglMatrixMode() and
+  the matrix stack via lglPushMatrix() and lglPopMatrix(). For the
+  latter operations the matrix mode can be LGL_PROJECTION,
+  LGL_MODELVIEW or LGL_TEXTURE.
+
+* Projection and viewing matrices can be calculated using the
+  lglPerspective(), lglOrtho(), lglFrustum() and lglLookAt()
+  methods. This corresponds to the former GL and GLU utility methods
+  gluPerspective(), glOrtho(), gluOrtho2D, glFrustum and gluLookAt().
+
+* For the calculation of the above 4x4 matrices the glVertex library
+  is utilizing the GLSLmath C++ header-only math library, which is
+  part of the distribution.
+
+* For convenience, the library extends the above API with the
+  lglProjection(), lglModelView(), lglView() and lglModel()
+  methods. These simplify the setup of the model-view and projection
+  matrices, since they do not require an explicit change of the matrix
+  mode.
+
+* Matrix operations between lglBegin() and lglEnd() are not allowed.
+
+* Vertices are specified with lglVertex() after starting a sequence
+  with lglBegin(). The specified vertices are gathered in a VBO, which
+  is rendered on lglEnd(). Supported graphics primitives are:
+
+  * LGL_LINES, LGL_LINE_STRIP
+  * LGL_TRIANGLES, LGL_TRIANGLE_STRIP, LGL_TRIANGLE_FAN
+  * LGL_QUADS, LGL_QUAD_STRIP
+
+* If the vertices are gathered in an C++ object of type "lglVBO", they
+  are not rendered immediately on lglEnd() but on an explicit
+  lglRender() call. This enables multiple render calls on the same
+  pre-compiled VBO. The center of the vertices' bounding box is
+  available via lglGetCenter() and the extent of the bounding box is
+  available via lglGetExtent().
+
+* In the above case, multiple lglBegin() / lglEnd() sections are
+  allowed, if the primitive types are matching. If the primitive type
+  is LGL_TRIANGLE_STRIP or LGL_QUAD_STRIP, then the strip sections are
+  concatenated to form a single strip by adding degenerate triangles
+  between the strip sections. This is the fastest available rendering
+  option, since it allows to maximize the number of triangles sent to
+  the graphics pipeline in a single batch.
+
+* In the above case, it is allowed to perform matrix operations
+  between lglBegin() and lglEnd(), if the matrix mode is set to
+  LGL_PREMODEL. In that case, all vertices are immediately
+  pre-multiplied with the top matrix of the pre-model matrix stack.
+
+* In the above case, the "lglSharedVBO" container class allows to
+  organize multiple instances of the same shared VBO so that it is
+  rendered at different locations. Each matrix appended to the
+  container via push_back yields another shared VBO object.
+
+* Vertex attributes are specified via lglColor(), lglNormal() and
+  lglTexCoord() before lglVertex().
+
+* Attributes specified outside of lglBegin() and lglEnd() do not take
+  effect, except for colors. If colors are specified outside of
+  lglBegin() and lglEnd() those colors modulate the colors specified
+  in between. The default vertex color is white. The effect of
+  coloring can be disabled with lglColoring(false).
+
+* The wireframe silhouette of each rendered triangle can be displayed
+  by setting the polygon mode to LGL_LINE via lglPolygonMode().
+
+* With lglManip() a simple track ball can be implemented. By mapping
+  mouse deltas to rotating angles and passing them to lglManip(), the
+  scene will be displayed rotated about an anchor point in viewing
+  coordinates. By default the scene rotates around the lookat point as
+  specified by lglLookAt() or lglView(). The corresponding rotation
+  matrix is available via lglGetManip()
+  resp. lglGetInverseTransposeManip(), if provided by the windowing
+  subsystem (e.g. Qt).
+
+* The specification of per-vertex colors (with lglColor) automatically
+  triggers the setup of a default GLSL shader, which interpolates the
+  colors during rasterization. Further lighting or texturing
+  operations modulate that color.
+
+* The specification of per-vertex normals (with lglNormal)
+  automatically triggers the setup of a default GLSL shader, which
+  performs Blinn-Phong shading. The latter can be configured with the
+  lglLight() method, which takes the usual Blinn-Phong lighting terms
+  as parameters for a single directional or positional light
+  source. If the light source is not defined to be a camera light, the
+  light vector is multiplied with the inverse transpose of the actual
+  model-view matrix. To define the light vector in world coordinates,
+  the model-view matrix must therefore contain the viewing matrix. The
+  default setting is a white directional light source positioned at
+  the origin of the camera coordinate system, which modulates the
+  vertex colors. The effect of lighting can be disabled with
+  lglLighting(false).
+
+* The specification of per-vertex texture coordinates (with
+  lglTexCoord) automatically triggers legacy 2D resp. 3D texturing
+  using a corresponding default GLSL shader. This requires the
+  specification of a texture object via lglTexture2D() or
+  lglTexture3D(). Texture objects can be created either as plain
+  texture map via lglCreateTexmap2D() or as mip-mapped texture via
+  lglCreateMipmap2D(). Volumetric textures are created with
+  lglCreateTexmap3D(). Texture coordinates are multiplied with the top
+  matrix of the texture matrix stack. For convenience, we can specify
+  the texture matrix via lglTex() without explicitly setting the
+  matrix mode to LGL_TEXTURE. The texture color is always modulating
+  the vertex color. The effect of texturing can be disabled with
+  lglTexturing(false).
+
+* If texture coordinate generation is turned on via lglTexCoordGen(),
+  then vertex positions are automatically interpreted as texture
+  coordinates, meaning that texture coordinates are identical to
+  object space coordinates. This is helpful for procedural
+  texturing. For this use case a 3D Perlin noise texture can be
+  created with lglCreateNoiseTexmap3D().
+
+* Clip planes are specified identically to the legacy OpenGL 1.2
+  specification by passing the coefficients a, b, c and d of the clip
+  plane equation ax+by+cz+d=0 to lglClipPlane(a, b, c, d, n), where n
+  is the number of the clip plane to be used. Up to 8 clip planes are
+  supported by default.
+
+* Fog parameters can be specified with lglFog(d, c). The first
+  parameter d controls the density of the fog, whereas the second
+  parameter c defines the fog color. If the density is zero, fog is
+  disabled. The fog factor f being used for blending with the fog
+  color is:
+
+  * w = 1/gl_FragCoord.w
+  * f = 1-exp(-density*w*w)
+
+* The state of the OpenGL rasterization can be controlled with the
+  following convenience functions: lglDepthDest(),
+  lglBackFaceCulling(), lglBlendMode(), lglAlphaTest(), lglRGBAWrite,
+  lglZWrite and lglLineWidth().
+
+* To specify a custom GLSL shader, we compile or load a shader via
+  lglCompileGLSLProgram() resp. lglLoadGLSLProgram() and pass the
+  corresponding GLSL program id to lglUseProgram(). Generic vertex
+  attributes to be used by the custom shader are specified with
+  lglAttribute() within lglBegin() / lglEnd() sections. Uniform shader
+  variables are set with lglUniform*(). The usage of the custom shader
+  and uniforms is limited to the VBO on which the shader and uniforms
+  have been set locally. Uniforms can be copied from one VBO to
+  another by calling lglCopyUniforms(). To render a VBO with a custom
+  program and a local set of uniforms, call vbo.lglUseProgram(),
+  vbo.lglUniform() and vbo.lglRender() on the VBO object "vbo". To
+  render a set of VBOs with a consistent program and set of uniforms,
+  call lglUseProgram(), lglUniform() and lglRender(vbo) globally. To
+  disable a custom shader, call lglUseDefaultProgram(). The disposal
+  of unused custom shaders needs to be handled explicitly via
+  lglDeleteGLSLProgram().
+
+* To replace the internal default shader, which is used if no custom
+  shader is specified, we pass a compiled program id to
+  lglReplaceDefaultProgram(id, colors, normals, texcoords), where the
+  latter three parameters determine whether or not the shader is
+  taylored for receiving color, normal or texture coordinate
+  attributes as attached to the actually rendered vertices. The
+  replaced shader will be active for all VBOs, which have no custom
+  shader and match the specified set of vertex attributes. A
+  replacement shader can be specified for each different set of
+  attributes (meaning a total of 8 auto-selected replacement
+  shaders). It is recommended to use VBOs with normals but no color or
+  texture coordinate attributes by default and specify a replacement
+  shader for this default attribute set via
+  lglReplaceDefaultProgram(id).
+
+For more information about GLSL shaders see the following examples:
+
+----
+
+GLSL SHADER EXAMPLE:
+
+If both color and normal attributes are supplied along each vertex,
+the glVertex library uses the following default GLSL shader (which has
+been simplified to make it better readable), which performs
+single-sided Blinn-Phong shading for either a directional or a
+positional light source:
+
+Default Vertex Shader:
+
+~~~~
+#version 120
+attribute vec4 vertex_position;
+attribute vec4 vertex_color;
+attribute vec3 vertex_normal;
+uniform mat4 mv;
+uniform mat4 mvp;
+uniform mat4 mvit;
+uniform vec4 light;
+varying vec4 frag_color;
+varying vec3 frag_normal;
+varying vec3 frag_halfway;
+varying vec3 frag_lightvec;
+vec3 flightvec(vec4 mv_pos) {return((light.w==0.0f)? vec3(light) : vec3(light - mv_pos));}
+vec3 flightdir(vec4 mv_pos) {return((light.w==0.0f)? vec3(light) : normalize(vec3(light - mv_pos)));}
+vec4 fvertex() {return(mvp * vertex_position);}
+vec3 fnormal() {return(normalize(mat3(mvit) * vertex_normal));}
+vec3 fhalfway(vec4 mv_pos) {return(normalize(flightdir(mv_pos) - normalize(vec3(mv_pos))));}
+void main()
+{
+   vec4 mv_pos = mv * vertex_position;
+   frag_color = vertex_color;
+   frag_normal = fnormal();
+   frag_halfway = fhalfway(mv_pos);
+   frag_lightvec = flightvec(mv_pos);
+   gl_Position = fvertex();
+}
+~~~~
+
+Default Fragment Shader:
+
+~~~~
+#version 120
+uniform vec3 kaIa,kdId,ksIs;
+uniform float exponent;
+uniform vec3 falloff;
+varying vec4 frag_color;
+varying vec3 frag_normal;
+varying vec3 frag_halfway;
+varying vec3 frag_lightvec;
+vec4 flighting(vec4 color)
+{
+   vec3 n = normalize(frag_normal);
+   vec3 h = normalize(frag_halfway);
+   vec3 l = normalize(frag_lightvec);
+   float d = length(frag_lightvec);
+   float diffuse = dot(l, n);
+   float specular = dot(h, n);
+   float attenuation = 1.0f / (falloff.x + falloff.y*d + falloff.z*d*d);
+   diffuse = (diffuse &amp;lt; 0.0f)? 0.0f : diffuse;
+   specular = pow((specular &amp;lt; 0.0f)? 0.0f : specular, exponent);
+   attenuation = (attenuation &amp;gt; 1.0f)? 1.0f : attenuation;
+   return(vec4(vec3(color) * (kaIa + kdId * diffuse * attenuation) + ksIs * specular * attenuation, color.a));
+}
+void main()
+{
+   gl_FragColor = flighting(frag_color);
+}
+~~~~
+
+If the polygon mode is set to LGL_LINE with lglPolygonMode(), the
+above shaders are replaced with a single-pass GLSL shader that
+calculates the wire frame silhouette of each triangle by using
+barycentric coordinates.
+
+The default shader can be overridden by setting a custom GLSL shader
+via lglUseProgram(). Then the GLSL program must comply to the
+following rules:
+
+* Vertices are passed in the attribute "vertex_position" (vec4).
+* Colors are passed in the attribute "vertex_color" (vec4).
+* Normals are passed in the attribute "vertex_normal" (vec3).
+* Texture coordinates are passed in the attribute "vertex_texcoord" (vec4).
+* Generic vertex attributes are passed in "vertex_attribute0",
+  "vertex_attribute1", "vertex_attribute2", ...
+* The vertex shader is required to use the model-view-projection
+  matrix "mvp" and transform the vertices with that matrix (uniform
+  mat4 mvp).
+* If no color attributes were specified between lglBegin() and
+  lglEnd(), the fragment shader may use the actual color instead
+  (uniform vec4 color).
+* If normals were specified, the vertex shader may use the model-view
+  matrix "mv" resp. the inverse transpose model-view matrix "mvit" to
+  transform the vertex normals.
+* If texture coordinates were specified, the vertex shader may use the
+  uniform texture matrix "tm" and transform texture coordinates with
+  that matrix.
+* The vertex shader is required to write "gl_Position".
+* The fragment shader is required to write "gl_FragColor".
+
+To setup a custom shader, we can load the GLSL source like so:
+
+~~~~
+const char vertex_shader_file[] = "vertex_shader.frg";
+const char fragment_shader_file[] = "fragment_shader.vtx";
+...
+GLuint program = lglLoadGLSLProgram(vertex_shader_file, fragment_shader_file);
+lglUseProgram(program);
+...
+lglDeleteGLSLProgram(program);
+~~~~
+
+If the shader sources are available as a single shader file with the
+extension ".glsl", where the vertex and fragment shaders have been
+concatenated with the separator "---", we can load the combined shader
+as follows:
+
+~~~~
+const char shader_file[] = "shader.glsl";
+GLuint program = lglLoadGLSLProgram(shader_file);
+~~~~
+
+If the combined shader program source is defined inline as a C-string,
+we can compile the shader as follows:
+
+~~~~
+const char shader[] = "#version 120\n ...";
+...
+GLuint program = lglCompileGLSLProgram(shader);
+~~~~
+
+The shortest possible combined shader program is the following:
+
+~~~~
+#version 120
+attribute vec4 vertex_position;
+uniform mat4 mvp;
+void main()
+{
+   gl_Position = mvp * vertex_position;
+}
+---
+#version 120
+uniform vec4 color;
+void main()
+{
+   gl_FragColor = color;
+}
+~~~~
+
+The above shader program is called the "plain shader". Compiling and
+activating this shader is equivalent to:
+
+~~~~
+GLuint program = lglCompileGLSLProgram(lglPlainGLSLProgram());
+...
+lglUseProgram(program);
+...
+lglDeleteGLSLProgram(program);
+~~~~
+
+If a shader contains uniform variables (besides the mandatory mv, mvp
+and mvit uniforms) we can set those uniforms via lglUniform*() for the
+currently active GLSL program. The uniforms needs to be specified after
+lglUseProgram():
+
+~~~~
+lglUseProgram(program);
+...
+lglUniformi("uniform int", 0);
+lglUniformf("uniform float", 0.0f);
+lglUniformfv("uniform vec3", vec3f(0));
+lglUniformfv("uniform vec4", vec4f(0));
+lglUniformfv("uniform mat3", mat3f(1));
+lglUniformfv("uniform mat4", mat4f(1));
+~~~~
+
+Each of the lglUniform*() functions returns an index, which can be
+used to set frequently changing uniform values directly:
+
+~~~~
+unsigned int index = lglUniform("uniform");
+lglUniform*(index, ...);
+~~~~
+
+Uniform samplers can be set with lglSampler2D/3D(), which is just a
+convenience wrapper around lglUniformi() and lglTexture2D/3D().
+
+When a different program id is passed to lglUseProgram(id), the list
+of uniforms previously registered with lglUniform*() is cleared. If it
+is necessary to keep the current list of uniforms, we may pass false
+as second parameter: lglUseProgram(id, false).
+
+----
+
+GLSL SHADER EXAMPLE /W FOGGING:
+
+In this example we use Qt to create an OpenGL core profile and a
+custom GLSL shader that implements simple exponential fogging:
+
+~~~~
+static const char vertex_shader[] =
+   "#version 120\n"
+   "attribute vec4 vertex_position;\n"
+   "attribute vec4 vertex_color;\n"
+   "uniform mat4 mvp;\n"
+   "varying vec4 frag_color;\n"
+   "vec4 fvertex() {return(mvp * vertex_position);}\n"
+   "void main()\n"
+   "{\n"
+   "   frag_color = vertex_color;\n"
+   "   gl_Position = fvertex();\n"
+   "}\n";
+
+static const char fragment_shader[] =
+   "#version 120\n"
+   "uniform float density;\n"
+   "varying vec4 frag_color;\n"
+   "void main()\n"
+   "{\n"
+   "   float w = 1.0f/gl_FragCoord.w;\n"
+   "   w = 1.0f-exp(-density*w*w);\n"
+   "   gl_FragColor = (1.0f-w)*frag_color + w*vec4(1);\n"
+   "}\n";
+
+lglVBO vbo;
+GLuint program = vbo.lglCompileGLSLProgram(vertex_shader, fragment_shader);
+vbo.lglUseProgram(program);
+vbo.lglUniformf("density", 0.1f);
+~~~~
+
+Remark: The above shader is equivalent to using lglFog(density).
+
+To compile and run the Qt example, type the following command line:
+
+&amp;gt; make qt &amp;amp;&amp;amp; ./qt_example
+
+----
+
+OBJ FORMAT EXAMPLE:
+
+The glVertex library supports the OBJ file format (as outlined in the
+Alias Wavefront OBJ file format section). In the following example we
+load the famous Utah teapot, which is actually a German Melitta
+teapot, into a VBO:
+
+~~~~
+#include &amp;lt;glvertex_objformat.h&amp;gt;
+
+...
+
+lglVBO *vbo = lglLoadObj("teapot.obj");
+if (vbo == NULL) lglFatal("file not found");
+
+...
+
+{
+   lglPushMatrixScoped();
+   lglScale(0.005);
+   vbo-&amp;gt;lglRender();
+}
+~~~~
+
+For more details, see the full source code of the Qt example in
+"examples/qt_example.cpp". The Qt example shows how to load multiple
+obj files via lglLoadObj(). It also features a track ball. The track
+ball is inherited from the "lgl_Qt_GLUI" window class, which opens a
+Qt window with an OpenGL core profile context and uses lglManip() to
+manipulate the orientation of the rendered scene depending on the
+mouse events observed.
+
+----
+
+SHARED VBO EXAMPLE:
+
+In case we want to render a particular geometric object multiple
+times, we can create a single VBO for the object and use lglModel() to
+render the object at different locations. With the "lglSharedVBO"
+container class, we can simplify the calculation of the modeling
+matrices that need to be passed to lglModel() by using the pre-model
+matrix stack:
+
+~~~~
+lglVBO *vbo = lglLoadObj("teapot.obj");
+lglSharedVBO vbos(vbo);
+
+lglMatrixMode(LGL_PREMODEL);
+for (unsigned int i=-10; i&amp;lt;=10; i++)
+{
+   lglPushMatrix();
+      lglTranslate(i,0,0);
+      if (i%2) lglRotate(90, 0,1,0);
+      vbos.push_back();
+   lglPopMatrix();
+}
+lglMatrixMode(LGL_MODELVIEW);
+
+...
+
+vbos.lglRender();
+~~~~
+
+For more details, see the full source code of the Qt pythagorean
+example in "qt_examples/qt_pythtree.cpp". This example shows how to
+create a VBO for a pythagorean tree and then renders an entire forest
+of those trees. It also demonstrates how to use Perlin noise for
+procedural texturing purposes. Hit the return key to see a single tree
+or the entire forest. To compile it on the command line type:
+
+&amp;gt; (cd qt_examples; qmake qt_pythtree.pro &amp;amp;&amp;amp; make)
+
+----
+
+REPLACEMENT SHADERS:
+
+In case we want to render multiple objects with a custom shader, that
+is consistent for all objects, we replace the default internal shader
+by a custom one:
+
+~~~~
+GLuint id = lglCompileGLSLProgram(custom_program);
+lglReplaceDefaultProgram(id);
+lglUniform("custom_uniform", custom_value);
+lglRender(vbo1);
+lglRender(vbo2);
+lglRender(vbo3);
+...
+lglDeleteGLSLProgram(id);
+~~~~
+
+Note that the internal shader is chosen depending on the set of
+attributes available in the VBO. The default attribute set includes
+normals but no color or texture coordinate attributes. As a
+consequence, the above custom shader only applies to VBOs with a
+respective attribute set. To replace a shader for a different
+attribute set, add respective boolean parameters to
+lglReplaceDefaultProgram:
+
+~~~~
+bool colors = ...;
+bool normals = ...;
+bool texcoords = ...;
+lglReplaceDefaultProgram(id, colors, normals, texcoords);
+~~~~
+
+----
+
+LIGHT SOURCES AND MATERIALS:
+
+In order to allow a more convenient specification of the lighting
+parameters, we first define and enable a light source and then define
+and enable a material, which together affect the actual Blinn-Phong
+lighting setup:
+
+~~~~
+static lgl_LightSource light;
+light.begin();
+static lgl_Material material;
+material.begin();
+lglRender(...);
+material.end();
+light.end();
+~~~~
+
+The currently active light source is used to determine the light
+vector (via setDirection resp. setPosition) and intensity (via
+setAmbientColor, setDiffuseColor, setSpecularColor), e.g. for a
+directional camera light source:
+
+~~~~
+light.setDirection(vec3f(0,0,1));
+light.setAmbientColor(vec3f(1));
+light.setDiffuseColor(vec3f(1));
+light.setSpecularColor(vec3f(1));
+~~~~
+
+A positional light source also supports constant, linear and quadratic
+attenuation coefficients (via setIntensityAttenuation), e.g. for a
+positional camera light source:
+
+~~~~
+light.setPosition(vec3f(0,0,0));
+light.setAmbientColor(vec3f(1));
+light.setDiffuseColor(vec3f(1));
+light.setSpecularColor(vec3f(1));
+light.setIntensityAttenuation(vec3f(0,0,0.001f));
+~~~~
+
+The currently active material is used to determine the material
+reflection (via setAmbientColor, setDiffuseColor, setSpecularColor,
+setSpecularExponent), e.g:
+
+~~~~
+material.setAmbientColor(vec3f(0.1f));
+material.setDiffuseColor(vec3f(0.7f));
+material.setSpecularColor(vec3f(0.2f));
+material.setSpecularExponent(30);
+~~~~
+
+----
+
+LGL SCENE GRAPH:
+
+The glVertex package contains a scene graph module that is easy to
+understand and use for OpenGL beginners. It is intended to be used for
+the construction of complex graphical objects from a set of primitive
+shapes with unit size. For this purpose it contains a base node class
+(lgl_Node) and four main scene graph node types derived from the base
+class:
+
+* lgl_GeometryNode: encapsulates geometry by means of a VBO
+  * the VBO is given as a reference to a lglVBO object
+* lgl_ContainerNode: encapsulates geometry by means of a VBO
+  * the VBO is owned by the node
+* lgl_TransformationNode: encapsulates transformations like
+  * translation, rotation and scaling
+* lgl_CameraNode: encapsulates the camera transformation
+  * accounts for both the projection and the view transformation
+
+The hierarchical construction of a scene is accomplished by adding
+child nodes to their parents via the add() method. A geometry node is
+usually a leave node of the scene graph and all the transformations
+from the root of the scene graph to the geometry node are applied to
+it in descending order.
+
+Added nodes are reference counted, so that they do not need to be
+released explicitly. They are released automatically, when the last
+referencing node is released.
+
+The add() method allows chaining, so that the addition of a geometry
+node and its transformations can be written as a single command. See
+the following example:
+
+~~~~
+#include &amp;lt;glvertex_nodes.h&amp;gt;
+
+...
+
+// vbo
+lglCube *cube = new lglCube();
+
+// camera
+lgl_CameraNode *cam = new lgl_CameraNode();
+cam-&amp;gt;setPerspective(fovy, aspect, nearp, farp);
+cam-&amp;gt;setEye(vec3(0,0,0), vec3(0,0,-1), vec3(0,1,0));
+root = new lgl_Node();
+root-&amp;gt;add(cam_);
+
+// scene
+root-&amp;gt;add(new lgl_TranslationNode(vec3(0,0,-10)))-&amp;gt;
+      add(new lgl_RotationAnimationNode(10, vec3(0,1,0))-&amp;gt;
+      add(new lgl_ScaleNode(vec3(3,1,1))-&amp;gt;
+      add(new lgl_GeometryNode(cube));
+
+root-&amp;gt;renderSceneGraph();
+~~~~
+
+List of available node types:
+
+* camera node (lgl_CameraNode)
+* geometry node (lgl_GeometryNode, lgl_ContainerNode)
+* VBO node (lgl_VBONode)
+* color node (lgl_ColorNode)
+* transformation node (lgl_TransformationNode)
+ * translation node (lgl_TranslationNode)
+ * rotation node (lgl_RotationNode)
+ * scale node (lgl_ScaleNode)
+* texture transformation node (lgl_TextureTransformationNode)
+* animation node (lgl_AnimationNode)
+ * translation animation node (lgl_TranslationAnimationNode)
+ * rotation animation node (lgl_RotationAnimationNode)
+* transition node (lgl_TransitionNode)
+ * translation transition node (lgl_TranslationTransitionNode)
+ * rotation transition node (lgl_RotationTransitionNode)
+ * scale transition node (lgl_ScaleTransitionNode)
+* warp animation node (lgl_WarpAnimationNode)
+* light node (lgl_LightNode)
+* 2D texture node (lgl_Texture2DNode)
+* 3D texture node (lgl_Texture3DNode)
+* state change node (lgl_StateNode)
+ * depth write node (lgl_DepthWriteNode)
+ * depth test node (lgl_DepthTestNode)
+ * back-face culling node (lgl_BackFaceCullingNode)
+ * blending node (lgl_BlendingNode)
+ * alpha test node (lgl_AlphaTestNode)
+ * fog node (lgl_FogNode)
+ * line width node (lgl_LineWidthNode)
+ * coloring node (lgl_ColoringNode)
+ * lighting node (lgl_LightingNode)
+ * texturing node (lgl_TexturingNode)
+* clipping node (lgl_ClippingNode)
+* switcher node (lgl_SwitcherNode)
+* level-of-detail node (lgl_LevelOfDetailNode)
+* subgraph node (lgl_SubgraphNode)
+* control node (lgl_ControlNode, lgl_SteerNode)
+* action node (lgl_ActionNode)
+
+The scene graph typically is created in the initializeOpenGL() method
+and rendered in the renderOpenGL() method of the Qt convenience class
+lgl_Qt_GLUI.
+
+Since the scene graph is aiming at the hierarchical construction of
+complex objects from unit shapes and not for handling an entire scene
+universe in the sense of a fully fledged game engine, it intentionally
+lacks the following features to keep the scene graph simple:
+
+* state sorting
+* bounding box culling
+* multi-pass rendering
+* support for transparency by depth sorting
+* advanced lighting and texturing techniques
+* physical simulation and collision detection
+* scene format loaders
+* picking and selection
+* etc.
+
+Nevertheless, a subset of the above features is provided by the
+following means:
+
+* The bounding box of the entire scene graph or any subgraph can be
+  determined by calling getBoundingBox() on the respective root or
+  sub-node. This method is not optimized. Calling getBoundingBox() on
+  a lgl_GeometryNode, lgl_ContainerNode or VBO is efficient, though.
+
+* View culling can be enabled for subsequent VBO rendering calls via
+  lglEnableViewCulling(), which culls the bounding box of each VBO
+  against the current view. Culling is turned off by
+  lglDisableViewCulling(). It is off by default.
+
+* Multi-pass rendering is provided via the lgl_SceneGraphScene class
+  (see below).
+
+* Picking is provided by the scene graph via pickSceneGraph() with a
+  picking ray defined in eye coordinates (see below). This method is
+  not optimized.
+
+* Transparency and selection is handled by the
+  lgl_GraphicalObjectScene class (see below).
+
+* Physical simulation is provided by the lgl_PhysicalObjects base
+  class. As a default implementation the Bullet library is wrapped in
+  the lgl_BulletObjects class (see below). Efficient picking is
+  provided via Bullet's collision system by calling
+  lgl_BulletObjects::rayTest on the scene.
+
+* Regarding scene graph optimizations, the following simple case is
+  supported: if multiple transformation nodes represent a node chain,
+  then the entire chain of transformations is merged into a single
+  transformation node containing the combined transformations. To
+  start the optimization, we call the optimizeAll() method on the root
+  node (see tutorial example "D01b_clockwork.cpp".
+
+For more details please check the following sections and the Doxygen
+documentation.
+
+----
+
+MULTI-PASS RENDERING:
+
+Multi-pass rendering is achieved by encapsulating a scene in an
+instance of a lgl_Scene class and passing this scene to an instance of
+a lgl_Renderer class.
+
+The scene class lgl_Scene
+* is an abstraction of a graphical scene
+* provides a pure virtual renderScene() method for rendering the scene
+* provides additional hooks for multi-pass rendering
+
+The scene class lgl_SceneGraphScene (derived from lgl_Scene)
+* is an abstraction of a graphical scene with a scene graph
+* provides multi-pass shadow plane rendering via setShadowPlane()
+* provides picking of objects stored as geometry nodes in the scene graph
+* provides view culling (enabled by default)
+
+The multi-pass renderer lgl_Renderer
+* is designed as an abstraction layer for multi-pass rendering
+* renders the referenced scene object multiple times
+* requires the scene object to provide hooks to setup the rendering state
+* calls the according hooks for each pass before and after the actual render call
+* provides multi-pass interlaced stereo rendering via setStereoMode()
+
+The multi-pass scene graph renderer lgl_SceneGraphRenderer (derived from lgl_Renderer)
+* is designed as a convenience wrapper for multi-pass scene graph rendering
+
+The lgl_Scene_GLUI class is a Qt convenience class based on the above
+multi-pass renderers that provides initialization and rendering hooks
+just like lgl_Qt_GLUI.
+
+If the scene supports interlaced stereo rendering, the lgl_Scene_GLUI
+convenience class understands the following command line options:
+* --stereo -&amp;gt; enable interlaced stereo rendering
+* --stereo=left -&amp;gt; enable horizontal left stereo interlacing mode
+* --stereo=right -&amp;gt; enable horizontal right stereo interlacing mode
+* --stereo=top -&amp;gt; enable vertical top stereo interlacing mode
+* --stereo=bottom -&amp;gt; enable vertical top stereo interlacing mode
+* --stereobase=... -&amp;gt; specify distance of eye points in stereo mode
+
+Please check the tutorial section for examples.
+
+----
+
+STEREO RENDERING:
+
+Stereo rendering is an example for multi-pass rendering. For the
+particular case of interlaced stereo, the LCD monitor commonly has
+alternating scan lines with different polarization. With glasses that
+show one polarization mode on the left and the other polarization mode
+on the right, two different stereo images can be provided in a single
+image. In such a setup the vertical resolution is halved.
+
+In order to generate a stereoscopic view of a particular scene, we
+need to render the scene two times. One time with one set of the scan
+lines disabled, and another time with the other set of complementary
+scan lines disabled. The eye point must match the position of the left
+resp. right eye. The distance of both is called the stereo base.
+
+With the multi-pass rendering module of glVertex this can be achieved
+easily by specifying the stereo base and the interlacing mode. Then
+the given scene is rendered automatically two times with proper scan
+line suppression and eye point displacement. For that we need to
+supply a camera object (lg_lCam) and the interlacing mode
+(lgl_interlacing_enum). The stereo base is a parameter on the camera
+(setStereoBase). The lines of sight of both eyes meet at the lookat
+point. The scene to be rendered is derived from the abstract lgl_Scene
+class by implementing the renderScene() method:
+
+~~~~
+lgl_Cam cam;
+cam.setPerspective(fovy, aspect, nearp, farp);
+cam.setEye(eye, lookat, up);
+cam.setStereoBase(base);
+
+class Scene: public lgl_Scene
+{
+public: void renderScene() {...}
+} scene;
+
+lgl_Renderer renderer;
+renderer.setScene(&amp;amp;scene);
+renderer.setStereoMode(&amp;amp;cam, LGL_INTERLACE_VERTICAL_TOP);
+~~~~
+
+Depending on the layout of the LCD's interlaced scan lines, the stereo
+mode (as given for the left eye) can be:
+
+* columns are numbered from left to right starting with 1
+* lines are numbered from top to bottom starting with 1
+* mode LGL_INTERLACE_HORIZONTAL_LEFT: odd vertical lines
+* mode LGL_INTERLACE_HORIZONTAL_RIGHT: even vertical lines
+* mode LGL_INTERLACE_VERTICAL_TOP: odd horizontal lines
+* mode LGL_INTERLACE_VERTICAL_BOTTOM: even horizontal lines
+
+For more details see the tutorial example
+"A08b_interlaced_stereo.cpp".
+
+----
+
+FBO RENDERING:
+
+Frame buffer objects (FBOs) are often used for multi-pass
+rendering. It is a common task to render a frame into a FBO in a first
+pass and to reuse the generated image as a texture in a second
+pass. The glVertex framework makes it very easy to create and use FBOs
+by providing the convenience class lglFBO:
+
+~~~~
+#include &amp;lt;glvertex_fbo.h&amp;gt;
+
+...
+
+// fbo declaration
+lglFBO fbo;
+
+...
+
+// create fbo and determine buffer size
+fbo.setupFBO(2048, 2048);
+
+...
+
+// fbo activation
+fbo.activateFBO();
+
+... render something into the fbo ...
+
+// fbo deactivation yields texture object id
+GLuint texid = fbo.deactivateFBO();
+
+... reuse fbo as texture ...
+
+~~~~
+
+Also see the tutorial example "A06_fbo.cpp".
+
+----
+
+PICKING:
+
+Picking is provided by means of a scene graph traversal. Calling
+pickSceneGraph(o, d) on the root node of a scene graph will return the
+closest VBO that is hit by a picking ray. The picking ray is defined
+by an origin o and a direction d. It is specified in eye
+coordinates. Picking is not optimized to be extremely efficient. It
+just uses a bbox test to check each VBO for intersection with the
+picking ray.
+
+Also see the tutorial example "A16_picking.cpp".
+
+----
+
+PHYSICAL SIMULATION:
+
+In order to simulate the physical behavior of moving and colliding
+objects, the lgl_BulletObjects class allows to setup a scene with
+physical objects. For this it utilizes the Bullet Physics library,
+which is auto-detected on compilation, when properly installed.
+
+Here is an example scene setup:
+
+~~~~
+lgl_BulletObjects *objects = new lgl_BulletObjects();
+objects-&amp;gt;setGravity(-9.81);
+
+lglSeed();
+for (int i=-1; i&amp;lt;=1; i++)
+   for (int j=-1; j&amp;lt;=1; j++)
+      for (int k=0; k&amp;lt;7; k++)
       {
-         vec h = p+l*d; // hit point
-         ...
+         lgl_BulletCubeObject *cube = new lgl_BulletCubeObject();
+         cube-&amp;gt;setColor(vec3(1,0.75,0.5));
+         cube-&amp;gt;setPhysicalMass(10);
+         cube-&amp;gt;setPhysicalRestitution(0.25);
+         cube-&amp;gt;scale(0.5);
+         cube-&amp;gt;move(vec3(1.5*i+0.001*(lglRandom()-0.5),k+0.25,1.5*j+0.001*(lglRandom()-0.5)));
+         addObject(cube);
+         lgl_BulletSphereObject *sphere = new lgl_BulletSphereObject();
+         sphere-&amp;gt;setColor(vec3(0.5,0.75,1));
+         sphere-&amp;gt;setPhysicalMass(10);
+         sphere-&amp;gt;setPhysicalRestitution(0.9);
+         sphere-&amp;gt;scale(0.5);
+         sphere-&amp;gt;move(vec3(1.5*i+0.001*(lglRandom()-0.5),k+0.75,1.5*j+0.001*(lglRandom()-0.5)));
+         addObject(sphere);
       }
-~~~~
-
-  Likewise, GLSLmath contains methods, which compute distances resp. intersections between:
-  * a point p and a line segment [a,b]: distance2line(p, a,b)
-  * a ray [p-&amp;gt;d] and an unit sphere: intersect_ray_unitsphere(p,d)
-  * a ray [p-&amp;gt;d] and an ellipsoid (o, r1/r2/r3): intersect_ray_ellipsoid(p,d, o,r1,r2,r3)
-  * a ray [o-&amp;gt;d] and a triangle [a,b,c]: ray_triangle_dist(o,d, a,b,c)
-  plus intersection tests between:
-  * a point p and a sphere (b,r^2): itest_point_sphere(p, b,r2)
-  * a ray [o-&amp;gt;d] and a sphere (b,r^2): itest_ray_sphere(o,d, b,r2)
-  * a ray [o-&amp;gt;d] and a cone: itest_cone_sphere(o,d, ...)
-  * a ray [o-&amp;gt;d] and a bounding box: itest_ray_bbox(o,d, ...)
-  * and some more ...
+
+lgl_GraphicalObjectScene::setObjects(objects);
+~~~~
+
+For more information see the tutorial example "A14_physical_objects.cpp".
+
+To compile it, we need to install bullet first. On Ubuntu the
+appropriate command line is "sudo apt-get install
+libbullet-dev". Otherwise we download the bullet source distribution,
+and type the following in the unpacked source directory:
+
+&amp;gt; cmake . &amp;amp;&amp;amp; make -j8 &amp;amp;&amp;amp; sudo make install
+
+After that we compile the above example by typing the following
+command line in the tutorial directory:
+
+&amp;gt; cmake . &amp;amp;&amp;amp; make A14_physical_objects &amp;amp;&amp;amp; ./A14_physical_objects
+
+----
+
+GETTING TRANSPARENCY RIGHT:
+
+Getting transparency right is more delicate than one would think in
+the first place. In general, a scene containing one or more
+semi-transparent objects needs to be rendered with a multi-pass
+technique as follows:
+
+The geometry is seperated into two rendering bins, where the first one
+contains the fully opaque objects and the second one contains the
+semi-transparent geometry. Then the bins are rendered in strict order.
+The first bin does not require anything special, but for the second
+bin an appropriate blending function has to be enabled and depth
+writing needs to be disabled.
+
+Now it very much depends on the blending function. If the blending
+function is commutative, (e.g. in the case of multiplicative or
+additive blending), we get away with just enabling the appropriate
+blend mode via lglBlendMode(LGL_BLEND_MULT)
+resp. lglBlendMode(GL_BLEND_ADD).
+
+Unfortunately, most situations require alpha blending, which means
+that we have a non-commutative blending function enabled via
+lglBlendMode(LGL_BLEND_ALPHA). In this case, the objects need to be
+depth-sorted from back to front (so called painter's algorithm).
+
+There is one notable exception, though: If a scene only contains
+semi-transparent geometry with exactly the same color (e.g. just
+semi-transparent gray windows), then depth sorting can be omitted.
+
+For the purpose of depth sorting, the first choice is usually the MPVO
+sorting algorithm (see Peter L. Williams, "Visibility Ordering Meshed
+Polyhedra"). This algorithm computes the depth order based on the
+visibility relationships of convex object shapes. For non-convex
+objects more elaborate algorithms are necessary (see Daniel Weiskopf
+et al., "GPU-Based Interactive Visualization Techniques").
+
+Since all those algorithms come at a substantial cost, a different
+approach is chosen for use cases, where performance is more important
+than accuracy, so that an approximate depth ordering approach can be
+utilized. To compute an approximate depth order, it is sufficient to
+sort the objects based on their eye distance (aka distance-based depth
+sorting). Then the visibility ordering will be close to the ones
+computed by the more elaborated algorithms, but in some special cases
+one will be able to spot the difference, although it might not be much
+apparent. And for the case of overlapping geometry one will never get
+it right without disecting the geometry.
+
+But the ordering will get close if the objects are sphere-shaped and
+do not differ much in size. If this is not the case, objects need to
+be subdivided until their sizes match. Alternatively, the Power-Sort
+algorithm can be applied, if the geometry is strictly convex (see
+Karasick et al., "Visualization of Three-Dimensional Delaunay
+Meshes"). Also see Stefan Roettger, "Volumetric Methods for the
+Real-Time Display of Natural Gaseous Phenomena", PhD Thesis,
+University of Stuttgart, Germany, 2004.
+
+After those theoretical discussions, we get back to using the glVertex
+library: In the case of a physical object simulation as outlined in
+the previous section, the glVertex library automatically applies a
+distance-based depth sort to the semi-transparent objects in the
+second geometry bin.
+
+For more information see the tutorial example "A15_depth_sorting.cpp".
+
+----
+
+OPENGL ES:
+
+The glVertex package works with traditional desktop OpenGL as
+described in detail in the preceding sections. It also works with
+OpenGL ES, when told like so:
+
+~~~~
+#define LGL_USE_GLES
+#include &amp;lt;glvertex.h&amp;gt;
+~~~~
+
+To check out an Android OpenGL ES example, open the
+"qt_examples/qt_teapot.pro" file of the Qt teapot example with Qt
+Creator. If you installed the Android SDK and NDK properly for Qt
+Creator, you may deploy the example to your Android device and see the
+famous Utah Melitta teapot spinning around in full-screen. For more
+info on Android deployment please see the according documentation on
+the Qt developer site.
+
+Note: For OpenGL ES the GLSL shader version must be either 100, 300 or
+310 corresponding to OpenGL ES 1.0, 3.0, or 3.1. For traditional
+OpenGL the GLSL version 120 corresponds to OpenGL 2.1, version 130
+corresponds to OpenGL 3.0, 140 to 3.1, 150 to 3.2, 330 to 3.3, and so
+on...
+
+----
+
+INCLUDING GLVERTEX INTO THIRD-PARTY SOFTWARE:
+
+When using the glVertex library in third-party software, it is
+required to include the glvertex header in the module, which uses it,
+as the first include file. When using it in multiple modules, it is
+recommended to create a global singleton "GL gl" and access the
+library's functions through that singleton:
+
+~~~~
+gl.lglSomething(...);
+~~~~
+
+You can also clone the state:
+
+~~~~
+lglCloneState(gl);
+lglSomething(...);
+~~~~
+
+The easiest way to create that global singleton is to set it up as a
+reference to a static local variable in a static method like so:
+
+~~~~
+static GL *getGL()
+{
+   static GL gl;
+   return(&amp;amp;gl);
+}
+
+GL *gl = getGL();
+gl-&amp;gt;lglSomething(...);
+~~~~
+
+----
+
+QT CONVENIENCE CLASSES:
+
+The glVertex package contains several convenience classes to easily
+setup a core profile with Qt.
+
+The most important ones are the "lgl_Qt_GLWindow" and
+"lgl_Qt_GLWidget" classes. The first class creates a system window
+with a core profile (Qt5 style), the second class creates a widget
+with a core profile (Qt4 style), that can be used just like any other
+Qt widget to construct a graphical user interface. To create a window
+with a core profile, we simply include the "glvertex_qt_glwindow.h" or
+"glvertex_qt_glwidget.h" header, derive from the respective class and
+implement the following two methods:
+
+* initializeOpenGL(): called once when the OpenGL context with a core
+  profile is available. Put OpenGL state initializations here, for
+  example glClearColor(1,1,1,1), glEnable(GL_DEPTH_TEST),
+  glDisable(GL_CULL_FACE) etc.
+
+* renderOpenGL(double dt): called continuously to enable animations
+  with a certain frame rate. Put OpenGL rendering commands here, for
+  example lglBegin(), lglVertex(), lglEnd() etc. The parameter dt
+  contains the elapsed time in seconds since the last rendered
+  frame. The frame rate can be set with the setFPS() method. The
+  default is 30 frames per second.
+
+Building on the above classes, the two derived classes
+"lgl_Qt_GLWindowUI" and "lgl_Qt_GLWidgetUI" both feature a track
+ball. They also inherit the following key commands:
+
+* ESC: quit
+* Ctrl-q: quit
+* Ctrl-z: toggle Z-test
+* Ctrl-c: toggle back-face culling
+* Ctrl-b: toggle alpha blending
+* Ctrl-a: toggle A-test
+* Ctrl-w: toggle wire frame mode
+* Ctrl-0: black background
+* Ctrl-1: white background
+* Ctrl-o: toggle override
+* Ctrl-f: toggle full-screen
+* Ctrl-r: reset manipulator
+* Space: toggle animation
+
+For quickly setting up an OpenGL prototyping application, it is
+recommended to derive from the "lgl_Qt_GLUI" class. To start with an
+empty programming template just copy the "qt_template" directory and
+fill in legacy-style OpenGL commands in the renderOpenGL() method in
+"qt_template.cpp".
+
+For your convenience, the lgl_Qt_GLUI class adds diagnostic OpenGL
+output, easy key handling via the overwritable keyPressed() method,
+mouse handling via a manipulator trackball and an overwritable
+doubleClick() method. By default, a double click will toggle the wire
+frame mode and the default keyPressed() implementation will check for
+the following additional keyboard shortcuts:
+
+* Ctrl-s: save screen snapshot
+* Ctrl-t: toggle continuous screen capture
+* Ctrl-p: toggle frame rate info
+* Ctrl-k: print key info
+
+The lgl_Qt_GLUI class also provides methods for handling command line
+arguments and options in the style "--option". Any option may contain
+a "=..."  appendix. The following methods are available to handle
+command line arguments:
+
+* args() -&amp;gt; number of arguments
+* opts() -&amp;gt; number of options starting with either "-" or "--"
+* hasOption("option") -&amp;gt; check for a particular option
+* getOptionString("option") -&amp;gt; get the associated option appendix string
+* getOptionValue("option") -&amp;gt; get the associated option appendix value
+
+By default, the lgl_Qt_GLUI convenience class understands the
+following options:
+* --help -&amp;gt; show usage info
+* --fullscreen -&amp;gt; toggle fullscreen mode
+* --wireframe -&amp;gt; toggle wireframe mode
+* --pause -&amp;gt; pause animations
+
+It also understands the standard Qt command line options, for example:
+* -geometry 1024x768-0-0
+
+Derived classes like lgl_Scene_GLUI (see below) may understand more
+options. Usage details are available with the "--help" option.
+
+The following example shows how to inherit from "lgl_Qt_GLUI", render
+a single rotating directionally lit diffuse triangle and toggle
+lighting on or off when pressing the Enter key or when a mouse double
+click is encountered:
+
+~~~~
+#include &amp;lt;glvertex_qt_glui.h&amp;gt;
+
+class Qt_GLWindow: public lgl_Qt_GLUI
+{
+public:
+
+   Qt_GLWindow() : lgl_Qt_GLUI() {}
+
+protected:
+
+   void initializeOpenGL()
+   {
+      // setup OpenGL
+      glClearColor(1,1,1,1);
+      glEnable(GL_DEPTH_TEST);
+      glDisable(GL_CULL_FACE);
+
+      // disable lighting
+      lglLighting(false);
+   }
+
+   void renderOpenGL(double dt)
+   {
+      // clear frame buffer
+      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+      // projection setup
+      double fovy = 90;
+      double aspect = (double)width()/height();
+      double nearp = 0.1;
+      double farp = 10;
+      lglMatrixMode(LGL_PROJECTION);
+      lglLoadIdentity();
+      lglPerspective(fovy, aspect, nearp, farp);
+
+      // viewing setup
+      lglMatrixMode(LGL_MODELVIEW);
+      lglLoadIdentity();
+      lglLookAt(0,0,1, 0,0,0, 0,1,0);
+
+      // define local rotated coordinate system
+      static double angle=0; // rotation angle in degrees
+      static const double omega=10; // rotation speed in degrees/s
+      angle+=dt*omega;
+      lglRotate(angle, 0,1,0);
+
+      // lighting setup
+      lglLightDirection(vec3f(0,0,1), true);
+      lglLightParameters(vec3f(0), vec3f(1), vec3f(0));
+
+      // render triangle
+      lglBegin(LGL_TRIANGLES);
+         lglColor(1,0,0);
+         lglNormal(-1,-1,1);
+         lglVertex(-0.5,-0.5,0);
+         lglColor(0,1,0);
+         lglNormal(1,-1,1);
+         lglVertex(0.5,-0.5,0);
+         lglColor(0,0,1);
+         lglNormal(0,1,1);
+         lglVertex(0,0.5,0);
+      lglEnd();
+   }
+
+   void keyPressed(char key)
+   {
+      if (key == '\r')
+         lglLighting(!lglGetLighting());
+   }
+
+   void doubleClick(double x, double y)
+   {
+      keyPressed('\r');
+   }
+
+};
+
+int main(int argc, char *argv[])
+{
+   QApplication app(argc, argv);
+
+   // create OpenGL window
+   Qt_GLWindow main;
+   main.resize(640, 480);
+   main.show();
+
+   // start event loop
+   return(app.exec());
+}
+~~~~
+
+See the full source code of the above Qt example in
+"qt_examples/qt_triangle.cpp". To compile it on the command line type:
+
+&amp;gt; (cd qt_examples; qmake qt_triangle.pro &amp;amp;&amp;amp; make)
+
+Or open the .pro file with Qt Creator and hit the Run button.
+
+Note: On MacOS X you need to tell Qt Creator, where the Qt
+installation is located: Tools -&amp;gt; Options -&amp;gt; Build &amp;amp; Run -&amp;gt; Qt
+Versions -&amp;gt; Add -&amp;gt; File Browser -&amp;gt; select appropriate "qmake" -&amp;gt;
+e.g. in "/usr/local/qt.../bin/". As an alternative you may also use
+XCode. To create the corresponding XCode projects you need to run the
+"generate.sh" script from the commandline.
+
+----
+
+GLSL EDITOR:
+
+The glVertex package comes with a GLSL editor based on Qt. It allows
+basic editing of vertex and fragment GLSL programs. The editor is not
+meant for experts, it is meant for beginners to have fun writing their
+very first GLSL programs with it. To compile and run the GLSL editor,
+type the following command line:
+
+&amp;gt; make editor &amp;amp;&amp;amp; ./qt_editor
+
+For more information please read the help text of the editor.
+
+----
+
+INLINE GLSL EDITOR:
+
+We can also edit any custom shader source while the program is
+running. For that purpose, we use the QT inline editor, which shows
+the actual shader source in a separate window. The inline editor
+assumes that the shader is given as an inline "const char shader[] =
+..." C-string. The editor will load that string from the source code
+and write the modified shader back as an inline C-string when the
+program is closed.
+
+~~~~
+#include &amp;lt;glvertex_qt_shadereditor.h&amp;gt;
+
+const char shader[] = "...";
+GLuint id = lglCompileGLSLProgram(shader);
+
+create_lgl_Qt_ShaderEditor("shader", &amp;amp;id);
+
+lglUseProgram(id);
+~~~~
+
+The first parameter to the above call is the variable name of the
+shader C-string. The second parameter is a pointer to the shader id as
+returned by the OpenGL GLSL compiler.
+
+----
+
+IMAGE FILE FORMATS AND TEXTURES:
+
+The glVertex library supports the PNM and RAW image file formats.
+
+Here is an example to load a PPM image file:
+
+~~~~
+#include &amp;lt;glvertex_pnmformat.h&amp;gt;
+
+unsigned char *image;
+int width, height, components;
+
+unsigned char *image = lglReadPnmImage("example.ppm", &amp;amp;width, &amp;amp;height, &amp;amp;components);
+if (!image) lglWarning("could not load pnm image");
+~~~~
+
+In the above example the component parameter is
+* 1 for grayscale images
+* 2 for grayscale 16-bit images
+* 3 for RGB images
+* 4 for RGBA images
+
+Here is an example to load a raw image file:
+
+~~~~
+#include &amp;lt;glvertex_rawformat.h&amp;gt;
+
+unsigned char *image;
+long long width, height;
+unsigned int components;
+
+unsigned char *image = lglLoadRawImage("image.256x256_3.raw", &amp;amp;width, &amp;amp;height, &amp;amp;components);
+if (!image) lglWarning("could not load raw image");
+~~~~
+
+In the above example the file format needs to be encoded into the file name:
+* as in name.size_cellformat.raw
+* e.g. name.256x256.raw (grayscale image)
+* e.g. name.256x256_3.raw (rgb image)
+* e.g. name.256x256_u2m.raw (16-bit msb unsigned grayscale image)
+* cell format modifiers:
+*  1 = 8 bit
+*  2 = 16 bit
+*  3 = rgb
+*  4 = rgba
+*  6 = rgb 16 bit
+*  8 = rgba 16 bit
+*  u = unsigned
+*  s = signed
+*  m = msb
+*  l = lsb
+* default modifiers = u1m
+
+Here is an example to load a PNM (or RAW) image file into a texture object:
+
+~~~~
+#include &amp;lt;glvertex_texformats.h&amp;gt;
+...
+GLuint texid = lglLoadTexture("image.ppm");
+...
+lglTexture2D(texid);
+~~~~
+
+With Qt as user interface library, the glVertex library also supports
+PNG, JPEG and all other formats supported by Qt.
+
+Here is an example to load a PNG image file into a texture object:
+
+~~~~
+#include &amp;lt;glvertex_qt.h&amp;gt;
+...
+GLuint texid = lglLoadQtTexture("image.png");
+...
+lglTexture2D(texid);
+~~~~
+
+----
+
+OBJECT FILE FORMAT (ALIAS WAVEFRONT OBJ):
+
+The library supports the Alias Wavefront OBJ file format (via
+lglLoadObj and lglSaveObj). This is a simple textual format for
+indexed face sets. It essentially defines vertices ("v"), normals
+("vn") and texture coordinates ("vt") each on a single line. Then the
+geometric primitives are given each on a single line by specifiying
+the corresponding vertex, normal and texture coordinate indices of the
+faces ("f"). Here is an example, which just specifies a single
+triangle face made up from three indexed vertices:
+
+~~~~
+v -1 -0.5 0
+v 1 -0.5 0
+v 0 0.5 0
+f 1 2 3
+~~~~
+
+The same example with texture coordinates (uv-mapping):
+
+~~~~
+v -1 -0.5 0
+v 1 -0.5 0
+v 0 0.5 0
+vt 0 0
+vt 1 0
+vt 0 1
+f 1/1 2/2 3/3
+~~~~
+
+And the same example with a single normal per face:
+
+~~~~
+v -1 -0.5 0
+v 1 -0.5 0
+v 0 0.5 0
+vn 0 0 1
+f 1//1 2//1 3//1
+~~~~
+
+The official OBJ format specification allows a face to be either a
+triangle or a quad (or even a polygon). The latter is not supported by
+the glVertex OBJ format reader, so if you want to export an object
+file with blender, you need to make sure to check the "triangulate
+faces" option. The library, however, supports the inofficial extension
+of specifying per-vertex colors by appending 3 additional values to
+the vertex specification:
+
+~~~~
+v -1 -0.5 0 1 0 0
+v 1 -0.5 0 0 1 0
+v 0 0.5 0 0 0 1
+f 1 2 3
+~~~~
+
+----
+
+QT GEARS:
+
+The "Qt Gears" example is a modern version of the "glxgears" demo, which
+has been part of the Mesa library for decades. See the full source
+code of the example in "qt_examples/qt_gears.cpp". To compile it on
+the command line type:
+
+&amp;gt; (cd qt_examples; qmake qt_gears.pro &amp;amp;&amp;amp; make)
+
+----
+
+TUTORIAL:
+
+The "tutorial" folder contains many more examples with respect to the
+OpenGL pipeline, VBOs and GLSL shaders. To compile the examples type
+"cmake . &amp;amp;&amp;amp; make -j8" on the command line. For more information please
+have a look at the tutorial README.
+
+----
+
+DOXYGEN DOCUMENTATION:
+
+A detailed API and class documentation is available via Doxygen. Just
+run the following command in the top level directory:
+
+&amp;gt; make docs
+
+This will generate HTML pages with according documentation in the
+"docs/html" folder.
+
+Note: To generate the documentation, the "doxygen" and "graphviz"
+software packages need to be installed.
+
+To read the documentation open the "index.html" file with a browser
+like Firefox:
+
+&amp;gt; firefox index.html
+
+----
+
+PLATFORM NOTES:
+
+This software is mainly intended to be used with OpenGL 2.1 and higher
+(resp. OpenGL ES 2.0 and higher). For OpenGL versions 3.0 and higher
+full support for VBOs and GLSL shaders is enabled as provided by the
+respective core profile. For OpenGL versions lower than 3.0, VBOs and
+GLSL shaders are still available, but of course no functionality that
+requires a core profile. For OpenGL versions less than 2.1 the library
+will fall back to OpenGL 1.2 compatibility mode, which means that the
+legacy OpenGL 1.2 API will be used. In this case vertex arrays will be
+used instead of vertex buffers and custom shaders will be silently
+ignored.
+
+On Linux and MacOS X all recent OpenGL drivers including Intel, NVIDIA
+and ATI drivers run considerably stable with this package. Same for
+Windows and OpenGL ES on Android.
+
+On some older versions of MacOS X, however, the vertex buffer object
+implementation is seriously broken. This may result in the improper
+display of multiple vertex buffers. To my knowledge at least MacOS X
+10.5 is affected. In this case it is recommended to upgrade to a more
+recent version such as MacOS X 10.11 or later.
+
+On some Linux platforms the GCC 4.8 and 4.9 packages contain a broken
+version of the GNU dynamic linker. On Ubuntu 14.04 LTS and Open SuSe
+13.1, for example, this may result in an immediate crash when
+dynamically preloading the NVIDIA OpenGL driver. Ubuntu 16.04 LTS with
+GCC 5.2 is not affected.

 ----

&amp;lt;/glvertex_qt.h&amp;gt;&amp;lt;/glvertex_texformats.h&amp;gt;&amp;lt;/glvertex_rawformat.h&amp;gt;&amp;lt;/glvertex_pnmformat.h&amp;gt;&amp;lt;/glvertex_qt_shadereditor.h&amp;gt;&amp;lt;/glvertex_qt_glui.h&amp;gt;&amp;lt;/glvertex.h&amp;gt;&amp;lt;/glvertex_fbo.h&amp;gt;&amp;lt;/glvertex_nodes.h&amp;gt;&amp;lt;/glvertex_objformat.h&amp;gt;&amp;lt;/glvertex.h&amp;gt;&amp;lt;/glfw&amp;gt;&amp;lt;/glvertex.h&amp;gt;&amp;lt;/glvertex.h&amp;gt;&amp;lt;/glslmath.h&amp;gt;&amp;lt;/glvertex.h&amp;gt;&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefan Röttger</dc:creator><pubDate>Tue, 28 Jan 2020 16:08:15 -0000</pubDate><guid>https://sourceforge.net01357bf5d674cca7ee975b1f68d653b8a553fb64</guid></item><item><title>Home modified by Stefan Röttger</title><link>https://sourceforge.net/p/glslmath/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v15
+++ v16
@@ -1,9 +1,9 @@
-GLSLmath version 1.19 as of 8.July.2019
+GLSLmath version 1.20 as of 28.January.2020
 ----

 GLSLmath is free software. It is licensed under the MIT license.

-The code is copyright 2014-2019 by Stefan Roettger.
+The code is copyright 2014-2020 by Stefan Roettger.
 Contact: snroettg at gmail

 ----
@@ -34,19 +34,20 @@
 "usr/local/include" on Linux platforms.

 Here is a usage example that declares a position vector in homogeneous
-coordinates and then rotates and translates that vector by multiplying
-it with a corresponding 4x4 matrix:
+coordinates and then scales, rotates and translates that vector by
+multiplying it with a corresponding 4x4 matrix:

 ~~~~
 #include &amp;lt;glslmath.h&amp;gt;

-vec4 v(3,0,0);
+vec4 v(1,0,0);

 std::cout &amp;lt;&amp;lt; "original vector: " &amp;lt;&amp;lt; v &amp;lt;&amp;lt; std::endl;

+mat4 S = mat4::scale(3);
 mat4 R = mat4::rotate(90, vec3(0,1,0));
 mat4 T = mat4::translate(vec3(1,0,-10));
-mat4 M = T*R;
+mat4 M = T*R*S;

 v = M*v; // yields (1,0,-13)

@@ -86,21 +87,22 @@
   "v = (0, 0, -10)"
 ~~~~

-* Getting the length of a vector:
+* Getting the length and norm of a vector:

 ~~~~
   vec3 v(0,3,4);
   double l = v.length(); // yields 5
-~~~~
-
-* Averaging two position vectors p1 and p2:
+  double l2 = v.norm(); // yields 25
+~~~~
+
+* Averaging two vectors p1 and p2:

 ~~~~
   vec3 p1(-10,0,0), p2(10,0,0);
   vec3 v = 0.5*(p1+p2); // yields (0,0,0)
 ~~~~

-* Linear interpolation of two position vectors p1 and p2:
+* Linear interpolation of two vectors p1 and p2:

   Let w be the linear interpolation factor in the range [0..1]:

@@ -197,6 +199,17 @@
   vec4 mix = color1.blend(color2); // yields (0.75,0,0.25,1)
 ~~~~

+* Procedural-style vector operations:
+
+  length of a vector v: length(v)
+  dot product of two vectors a and b: dot(a, b) 
+  cross product of two vectors a and b: cross(a, b)
+  norm of a vector v: norm(v)
+  normalization of a vector v: normalize(v)
+  reflection of a vector v at a surface normal n: reflect(v, n);
+  linear interpolation of two vectors a and b with factor w: lerp(w, a, b)
+  blending two colors a and b: blend(a, b)
+
 * Creating a 3x3 identity matrix:

 ~~~~
@@ -219,7 +232,13 @@
   mat3 D(vec3(1,2,3));
 ~~~~

-* Creating a 3x3 matrix from three row vectors and applying it to a position vector:
+* Getting the determinant of a 3x3 matrix:
+
+~~~~
+  double d = D.det();
+~~~~
+
+* Creating a 3x3 matrix from three row vectors and multiplying it with a vector:

 ~~~~
   mat3 M(vec3(0,1,0),
@@ -249,7 +268,7 @@
   mat3 Mr = mat3::rows(a,b,c, d,e,f, g,h,i);
 ~~~~

-* Creating an affine 4x4 matrix:
+* Creating an affine 4x4 matrix and multiplying it with a position vector:

   The matrix transforms homogeneous points from the local coordinate
   system to a coordinate system with the origin o and the coordinate
@@ -266,22 +285,41 @@
   v = T*v; // yields (3,4,3,1)
 ~~~~

+* Available 4x4 matrix transformations as defined by the OpenGL standard:
+
+  translation by a vector v: mat4::translate(v)
+  rotation about an axis a and an angle of d degrees: mat4::rotate(d, a)
+  scaling with a factor f: mat4::scale(f)
+
+* Procedural-style 4x4 matrix transformations:
+
+  translation by a vector v: translate(M, v)
+  rotation about an axis a and an angle of d degrees: rotate(M, d, a)
+  scaling with a factor f: scale(M, f)
+
+  The above procedures multiply the corresponding transformation
+  matrix onto a given matrix M (from the right-hand side).
+
 * Using mat4 for MVP calculations as defined by the OpenGL
   standard. The resulting matrix is transferred with glUniform:

 ~~~~
-  mat4 M = mat4::translate(0,0,-10) * mat4::rotate(90, vec3(0,1,0));
+  mat4 P = mat4::perspective(90,1,1,100);
   mat4 V = mat4::lookat(vec3(0,3,10), vec3(0,0,0), vec3(0,1,0));
-  mat4 P = mat4::perspective(90,1,1,100);
+  mat4 M = mat4::translate(0,0,-10) * mat4::rotate(90, vec3(0,1,0)) * mat4::scale(3);

   mat4 MVP = P*V*M;

   glUniformMatrix4fv(location, 1, GL_FALSE, (const float *)mat4f(MVP));
 ~~~~

-  Note that linear math calculations are done with double precision to
-  avoid numerical instabilities, but the transfer of the final matrix
-  to the gpu is done with single precision float accuracy!
+  Note that the order of matrix multiplications is the reverse of the
+  logical order of the applied transformations.
+
+  Also note that linear math calculations are done with double
+  precision to avoid numerical instabilities, but the transfer of the
+  final matrix to the gpu is done with single precision float
+  accuracy!

 * By default, matrices are multiplied from the right-hand side, e.g.:

@@ -302,8 +340,6 @@

 ~~~~
   mat4 M = MVP.invert().transpose();
-   or
-  mat4 M = transpose(invert(MVP));
 ~~~~

 * Special matrices:
@@ -318,7 +354,7 @@
    mat4 Mf = mat4:frustum(left, right, bottom, top, near, far);
 ~~~~

-The following convenience matrices can be constructed as well:
+For convenience, the following matrices can be constructed as well:

 ~~~~
    // create affine transformation matrix consisting of
@@ -330,14 +366,20 @@
    mat4 Mp = mat4:parallel(p, n, d);
 ~~~~

-* Hierarchical modelling with the scoped matrix stack:
+* Procedural-style matrix operations:
+
+  determinant of a matrix M: determinant(M)
+  transposition of a matrix M: transpose(M)
+  inversion of a matrix M: inverse(M)
+
+* Hierarchical modeling with the scoped matrix stack:

   Given the following scene graph with

 ~~~~
   + = root node
   C = camera
-  T0-T2 = modelling transformations
+  T0-T2 = modeling transformations
   G = geometry node

         +
@@ -381,7 +423,7 @@
   }
 ~~~~

-* Hierarchical modelling with the OpenGL matrix stack:
+* Hierarchical modeling with the OpenGL matrix stack:

   Given a scene where a glPushMatrix/glPopMatrix pair is required:

&amp;lt;/glslmath.h&amp;gt;&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefan Röttger</dc:creator><pubDate>Tue, 28 Jan 2020 16:03:07 -0000</pubDate><guid>https://sourceforge.nete54488717e76bf3e8bc06b0715d0254e95bc98f1</guid></item><item><title>Home modified by Stefan Röttger</title><link>https://sourceforge.net/p/glslmath/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v14
+++ v15
@@ -1,8 +1,14 @@
-GLSLmath version 1.17 as of 25.November.2017
+GLSLmath version 1.19 as of 8.July.2019
 ----

-GLSLmath is totally free software and licensed under the MIT license.
-The code is copyright 2014-2017 by Stefan Roettger.
+GLSLmath is free software. It is licensed under the MIT license.
+
+The code is copyright 2014-2019 by Stefan Roettger.
+Contact: snroettg at gmail
+
+----
+
+INTRODUCTION:

 GLSLmath consists of a single C++ header file.

@@ -411,10 +417,10 @@
 * HSV to RGB conversion:

 ~~~~
-  vec3 rgb1 = glslmath::hsv(0,1,1); // red
-  vec3 rgb2 = glslmath::hsv(60,1,1); // yellow
-  vec3 rgb3 = glslmath::hsv(120,1,0.25); // dark green
-  vec3 rgb4 = glslmath::hsv(240,0.5,1); // blueish
+  vec3 rgb1 = glslmath::hsv2rgb(0,1,1); // red
+  vec3 rgb2 = glslmath::hsv2rgb(60,1,1); // yellow
+  vec3 rgb3 = glslmath::hsv2rgb(120,1,0.25); // dark green
+  vec3 rgb4 = glslmath::hsv2rgb(240,0.5,1); // blueish
 ~~~~

 * 3D Perlin noise:
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefan Röttger</dc:creator><pubDate>Mon, 19 Aug 2019 09:05:57 -0000</pubDate><guid>https://sourceforge.netcf5c6dceffc09ecbb3c3ce8529ee777cdd211b25</guid></item><item><title>Home modified by Stefan Röttger</title><link>https://sourceforge.net/p/glslmath/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v13
+++ v14
@@ -1,4 +1,4 @@
-GLSLmath version 1.16 as of 20.October.2017
+GLSLmath version 1.17 as of 25.November.2017
 ----

 GLSLmath is totally free software and licensed under the MIT license.
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefan Röttger</dc:creator><pubDate>Sun, 26 Nov 2017 22:41:31 -0000</pubDate><guid>https://sourceforge.netaeb2800893a986f4352eee0c8cb73937f1855bd1</guid></item><item><title>Home modified by Stefan Röttger</title><link>https://sourceforge.net/p/glslmath/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v12
+++ v13
@@ -1,4 +1,4 @@
-GLSLmath version 1.15 as of 12.July.2017
+GLSLmath version 1.16 as of 20.October.2017
 ----

 GLSLmath is totally free software and licensed under the MIT license.
@@ -236,6 +236,13 @@
       \       0             0             1       /
 ~~~~

+* Creating a 3x3 matrix from three column resp. row vectors:
+
+~~~~
+  mat3 Mc = mat3::columns(vec3(a,b,c), vec3(d,e,f), vec3(g,h,i));
+  mat3 Mr = mat3::rows(a,b,c, d,e,f, g,h,i);
+~~~~
+
 * Creating an affine 4x4 matrix:

   The matrix transforms homogeneous points from the local coordinate
@@ -253,7 +260,8 @@
   v = T*v; // yields (3,4,3,1)
 ~~~~

-* Using mat4 for MVP calculations and transferring the matrix with glUniform:
+* Using mat4 for MVP calculations as defined by the OpenGL
+  standard. The resulting matrix is transferred with glUniform:

 ~~~~
   mat4 M = mat4::translate(0,0,-10) * mat4::rotate(90, vec3(0,1,0));
@@ -290,6 +298,30 @@
   mat4 M = MVP.invert().transpose();
    or
   mat4 M = transpose(invert(MVP));
+~~~~
+
+* Special matrices:
+
+The following matrices are supported as defined by the OpenGL standard:
+
+~~~~
+   // create orthographic projection matrix
+   mat4 Mo = mat4:ortho(left, right, bottom, top, near, far);
+
+   // create frustum projection matrix
+   mat4 Mf = mat4:frustum(left, right, bottom, top, near, far);
+~~~~
+
+The following convenience matrices can be constructed as well:
+
+~~~~
+   // create affine transformation matrix consisting of
+   // a rotation resp. non-singular matrix M and a translation vector v
+   mat4 Mt = mat4:transform(M, v);
+
+   // create parallel projection matrix defined by
+   // a plane point p and normal n and a projection direction vector v
+   mat4 Mp = mat4:parallel(p, n, d);
 ~~~~

 * Hierarchical modelling with the scoped matrix stack:
@@ -343,7 +375,7 @@
   }
 ~~~~

-* Hierarchical modelling with the opengl matrix stack:
+* Hierarchical modelling with the OpenGL matrix stack:

   Given a scene where a glPushMatrix/glPopMatrix pair is required:

@@ -353,7 +385,7 @@
    glPopMatrix();
 ~~~~

-  The above pair can be rewritten with the opengl scoped matrix stack:
+  The above pair can be rewritten with the OpenGL scoped matrix stack:

 ~~~~
    {
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefan Röttger</dc:creator><pubDate>Thu, 26 Oct 2017 15:59:29 -0000</pubDate><guid>https://sourceforge.net53db3393527e95e8e510e75fb5a2cb70dc1e8ec9</guid></item><item><title>Home modified by Stefan Röttger</title><link>https://sourceforge.net/p/glslmath/wiki/Home/</link><description>&lt;div class="markdown_content"&gt;&lt;pre&gt;--- v11
+++ v12
@@ -1,4 +1,4 @@
-GLSLmath version 1.14 as of 28.June.2017
+GLSLmath version 1.15 as of 12.July.2017
 ----

 GLSLmath is totally free software and licensed under the MIT license.
&lt;/pre&gt;
&lt;/div&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Stefan Röttger</dc:creator><pubDate>Fri, 14 Jul 2017 20:48:51 -0000</pubDate><guid>https://sourceforge.net4a9a0758612050a74e108c43a26b0a5d276be2bb</guid></item></channel></rss>