Course list http://www.c-jump.com/bcc/
OpenGL Mathematics (GLM) is a C++ mathematics library based on the OpenGL Shading Language (GLSL) specification.
GLM emulates GLSL's approach to vector/matrix operations whenever possible.
To use GLM, include glm/glm.hpp. Example from GLM manual:
#include <glm/glm.hpp> int foo() { glm::vec4 Position = glm::vec4( glm::vec3( 0.0 ), 1.0 ); glm::mat4 Model = glm::mat4( 1.0 ); Model[3] = glm::vec4( 1.0, 1.0, 0.0, 1.0 ); glm::vec4 Transformed = Model * Position; return 0; }
From GLSL specification 5.4.2:
If there is a single scalar parameter to a vector constructor, it is used to initialize all components of the constructed vector to that scalar's value:
glm::vec4 Position = glm::vec4( glm::vec3( 0.0 ), 1.0 );
If there is a single scalar parameter to a matrix constructor, it is used to initialize all the components on the matrix's diagonal, with the remaining components initialized to 0.0f
glm::mat4 Model = glm::mat4( 1.0 );
Matrix transformation is an extension of GLM. Example from GLM manual:
#include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> int foo() { glm::vec4 Position = glm::vec4( glm::vec3( 0.0f ), 1.0f ); glm::mat4 Model = glm::translate( glm::mat4( 1.0f ), glm::vec3( 1.0f ) ); glm::vec4 Transformed = Model * Position; return 0; }
glm::mat4 constructor that takes only a single value constructs a diagonal matrix:
glm::mat4 m4( 1.0f ); // construct identity matrix
The matrix has all zeros except for 1.0f set along the diagonal from the upper-left to the lower-right.
The default constructor glm::mat4() creates diagonal matrix with 1.0f diagonal, that is, the identity matrix:
glm::mat4 m4; // construct identity matrix
glm::mat4 glm::rotate( glm::mat4 const& m, float angle, glm::vec3 const& axis ); glm::mat4 glm::scale( glm::mat4 const& m, glm::vec3 const& factors ); glm::mat4 glm::translate( glm::mat4 const& m, glm::vec3 const& translation );
See official GLM documentation for other functions:
glm::frustum() glm::ortho() glm::lookAt() glm::perspective() glm::project(
glm::value_ptr takes any of the core template types. It returns a pointer to the memory layout of the object. For example, given
glm::mat4 m4( 1.0f ); // construct identity matrix
expressions
glm::value_ptr( m4 ) &m4[0][0]
are equivalent.
value_ptr() returns a direct pointer to the matrix data in column-major order, making it useful for uploading data to OpenGL.
Uploading data to OpenGL example:
#include <glm/glm.hpp> #include <glm/gtc/type_ptr.hpp> void f () { glm::vec3 aVector( 3 ); glm::mat4 someMatrix( 1.0f ); glUniform3fv( uniformLoc, 1, glm::value_ptr( aVector ) ); glUniformMatrix4fv( uniformMatrixLoc, 1, GL_FALSE, glm::value_ptr( someMatrix ) ); }
Each row and column in glm::mat4 is zero-based:
glm::mat4 m4( 1.0f ); // construct identity matrix m4[ 0 ] // column zero m4[ 0 ].x // same as m4[ 0 ][ 0 ] m4[ 0 ].y // same as m4[ 0 ][ 1 ] m4[ 0 ].z // same as m4[ 0 ][ 2 ] m4[ 0 ].w // same as m4[ 0 ][ 3 ]
Each column of matrix glm::mat4 is a vec4.
To set the entire column, e.g. for translation,
glm::mat4 m4( 1.0f ); // construct identity matrix m4[ 3 ] = glm::vec4( vec3( x, y, z ), 1.0f );
Related: see Chapter 6. Objects in Motion, Translation article from Learning Modern 3D Graphics Programming tutorial
Example of setting matrix m4 for scaling:
glm::vec3 scale( sx, sy, sx ); glm::mat4 m4( 1.0f ); // construct identity matrix m4[0].x = scale.x; m4[1].y = scale.y; m4[2].z = scale.z;
When using glm::translate( X, vec3 ), you are multiplying
X * glm::translate( Identity, vec3 )
This means translate first, then X
When using glm::rotate( X, vec3 ), you are multiplying
X * glm::rotate( Identity, vec3 )
This means rotate first, then X
When using glm::scale( X, vec3 ), you are multiplying
X * glm::scale( Identity, vec3 )
For example,
glm::mat4 transMatrix = glm::translate( glm::mat4( 1.0f ), glm::vec3( 0.0f, -0.5f, 0.0f ) ); planeModel->mM = glm::scale( // Scale first transMatrix, // Translate second glm::vec3( 100.0f, 100.0f, 100.0f ) );
Far all GLM transformation API, see GLM_GTC_matrix_transform at glm.g-truc.net
So the conventional Model-View-Projection should be multiplied in reverse:
glm::mat4 MVP = Projection * View * Model;
This means that Model transformation happens first, then View, and Projection is last.
Those are not the same!
See Chapter 6. Objects in Motion article from Learning Modern 3D Graphics Programming tutorial for details,