Welcome back to 3D Worlds and Matrix Transformations! You've successfully completed the first lesson, where we explored the mathematical foundations of transformation matrices. Now it's time to move from theory to practice as we implement these concepts using real code.
In this second lesson, we'll integrate the GLM (OpenGL Mathematics) library into our application and use it to create our first rotating 3D object. We'll take those beautiful matrix concepts from the previous lesson and see them come to life as we build a rotation matrix on the CPU and apply it directly to vertex positions. By the end of this lesson, we'll have a colorful square spinning at 45 degrees, demonstrating the power of matrix transformations in action.
GLM stands for OpenGL Mathematics, and it's essentially a C++ library that brings the mathematical power of GLSL (OpenGL Shading Language) directly to our CPU code. As you may recall from our previous lesson, we discussed how matrices can elegantly represent rotations, translations, and scaling operations. GLM provides us with ready-made functions to create these transformation matrices without having to write the mathematical computations ourselves.
The beauty of GLM lies in its design philosophy: it mirrors the syntax and functionality that we would use in shader code, making it easy to transfer mathematical concepts between CPU and GPU operations. Instead of manually constructing a 4×4 rotation matrix by calculating sine and cosine values, we can simply call glm::rotate() and let the library handle the mathematical details.
GLM is a header-only library, which means we don't need to link against any compiled binaries. We simply include the headers we need, and the compiler incorporates the necessary code directly into our application.
Let's start by examining the GLM headers we need for our transformation work. The library is organized into different modules, each providing specific mathematical functionality.
The first header, glm/glm.hpp, provides the core GLM functionality, including vector types like glm::vec3 and matrix types like glm::mat4. This gives us the basic mathematical data structures we'll use to represent positions, colors, and transformation matrices.
The second header, glm/gtc/matrix_transform.hpp, contains the transformation functions we discussed in our previous lesson: glm::rotate(), glm::translate(), and glm::scale(). These functions create the actual transformation matrices that will modify our 3D objects.
Now let's see how we can use GLM to represent our vertex positions and colors using proper mathematical types. GLM provides vector types that correspond exactly to what we learned about in our previous lesson.
Here, we're using glm::vec3 to represent both 3D positions and RGB color values. Each vector holds three float components, making it perfect for storing coordinates or color values . Notice how these are the four corners of our square, with each vertex having its own distinct color creating the beautiful gradient effect.
This is where the magic happens: we'll create our first transformation matrix using GLM. Remember from our previous lesson how we discussed that matrices encode coordinate system transformations? Now we'll see this in action.
Let's break this down step by step. We start with glm::mat4(1.0f), which creates a 4×4 identity matrix; this is our "do nothing" transformation that leaves objects unchanged. Then we pass this to glm::rotate() along with two additional parameters.
The second parameter, glm::radians(45.0f), specifies our rotation angle. GLM expects angles in radians rather than degrees, so we use glm::radians() to convert 45 degrees into the equivalent radian measurement. The third parameter, glm::vec3(0, 0, 1), defines our rotation axis. Since we want to rotate around the z-axis (like spinning a clock face), we specify the unit vector pointing along the z-axis.
GLM provides similar functions for other transformations: glm::translate(glm::mat4(1.0f), glm::vec3(x, y, z)) for moving objects and glm::scale(glm::mat4(1.0f), glm::vec3(sx, sy, sz)) for resizing them. Both follow the same pattern but without the angle parameter.
Now we come to the crucial step: applying our rotation matrix to each vertex position. This is where we see the power of matrix transformations in action, taking the theoretical concepts from our previous lesson and putting them to practical use.
This loop performs the heart of our transformation process. For each vertex position, we convert the 3D vector to a 4D vector by adding a w-component of 1.0f, creating what we call homogeneous coordinates. This allows our 4×4 matrix to properly handle both rotation and translation. We then multiply the rotation matrix by the position vector, which applies the transformation and gives us the rotated position.
Finally, we pack both the transformed position coordinates and the original color values into a flat array that OpenGL can use for rendering. Each vertex now occupies 6 consecutive floats in our array: three for position and three for color.
And that's it! Since we're using the same attribute formatting as last time, we don't need to change anything else in our OpenGL setup.
Our vertex positions have been transformed with the rotation matrix on our CPU, resulting in pre-calculated vertices that are already rotated 45 degrees around the z-axis. When we render this transformed geometry, OpenGL simply draws the vertices at their new positions, creating the visual effect of a rotated square.

We've successfully bridged the gap between mathematical theory and practical implementation! We integrated the GLM library into our application, created transformation matrices using GLM's intuitive functions, and applied CPU-based transformations to create our first rotated 3D object. The square now appears rotated 45 degrees, with each corner displaying a different color that creates a beautiful gradient effect.
This approach of transforming vertices on the CPU gives us complete control over the transformation process and helps us understand exactly how matrix mathematics affects our 3D geometry. In the upcoming practice exercises, you'll get hands-on experience implementing these GLM transformations yourself, experimenting with different rotation angles and axes to see how they affect the final rendered result.
