Opengl order of matrix transformations

AlvinfromDiaspar picture AlvinfromDiaspar · Apr 13, 2013 · Viewed 19k times · Source

Let's say I have a blue 3D box (where the top side is red colored).

  1. Now I call glScalef(1, 10, 1).
  2. Then I call glRotatef(90, 0, 1, 0).
  3. Then i render the cube.

What i expected is to see the the red side facing and stretched towards the screen (along the Y axis of the model).

But what im seeing is this: The red side is facing the screen (as expected). But the stretch is occurring on the Y axis of the view space (not the model).

I do know that if I set the scale along the Z axis, then i'll get the right result. But my confusion is that i thought scaling up on the Y axis, then rotating the box, would give me the right result.

What am i missing?

Answer

user1357649 picture user1357649 · Apr 14, 2013

OpenGL reads its matrices in what is known as column major order. The result is that each subsequent operation is a pre-multiplication of all the operations before it, not a post-multiplication. Thus, each subsequent call to an OpenGL operation (glScale, glTranslate, glRotate) is the first thing that affects an object, and it goes in reverse order from how you write it.

So, you need to change your multiplication order:

glRotatef(90, 0, 1, 0); // Notice how this is the first operation ...
// ... but will be applied after
glScalef(1, 10, 1); // This will be applied first, but is the last operation
// Zany, right?

Truth be told, it feels less intuitive when you're writing programs and using a computer to have to specify things in reverse order. But the Graphics Gods That Be decided that's how they wanted OpenGL's matrix stack to behave (along with HLSL, GLSL, and other systems: see the link above about column-major ordering).