3
votes

I migrate from my own matrix/vector operations to GLM and i don't understand one thing.

A model matrix in OpenGL - model_matrix = scale_matrix * rotate_matrix * translate_matrix, so we first translate then rotate and at last scale. But then i try to do so in GLM it shows quad at right place only if i use inverse order of multiplication (translate * rotate * scale), but works as it should for MVP matrix (projection * view * model).

Example code

using namespace glm;
mat4 projection = ortho(0.0f, 1.0f, 0.0f, 1.0f);
mat4 translate = translate(mat4(1.0f), vec3(0.5f, 0.5f, 0.0f));
mat4 rotate = rotate(mat4(1.0f), 90.0f, vec3(0.0f, 0.0f, 1.0f));
mat4 scale = scale(mat4(1.0f), vec3(0.5f, 0.5f, 1.0f));
mat4 m = translate * scale * rotate;// must be scale * rotate * translate
mat4 mvp = projection * mat4(1.0f)/*view matrix*/ * m;
glUseProgram(shader->prog);
glUniformMatrix4fv(shader->uniforms[0]/*um_mvp*/, 1, GL_FALSE, value_ptr(mvp));
...

Vertex shader

attribute vec3 av_pos;
attribute vec2 av_tex;

uniform mat4 um_mvp;

varying vec2 vv_tex;

void main()
{
 vv_tex = av_tex;
 gl_Position = um_mvp * vec4(av_pos, 1.0); 
} 
1
"A model matrix in OpenGL - model_matrix = scale_matrix * rotate_matrix * translate_matrix" Says who? Are you talking about what the glRotate/Scale/Translate functions did? Or are you talking about something else?Nicol Bolas
Well is't it? If we translateX(5) * scaleX(2.0) we scale coords system x to 2.0 then move to 10 instead of 5 units because of that, if we scaleX(2.0) * translateX(5) then we move to 5 units then scale coords system, order matters, no?Aristarhys

1 Answers

14
votes

so we first translate then rotate and at last scale.

... Well, quite the opposite.

Your "complete" matrix looks like this (leaving the rotate aside for simplicity) :

proj * view * translate * scale

, right ? Well this is correct: this means that your point X will be transformed this way :

proj * view * translate * scale * X

, which means that you will first apply scale, then translation, then positioning relative to the camera, then projection. Which is perfect.

Your problem seems to be the "scale-before-translate" stuff. Imagine a translation of 10 on the X axis, a scale of 2. You apply your matrix on, say, a ship.

  • You scale your ship. You have now a big ship, but still at the origin
  • You translate your ship. It's now still as big, but at 10 units of the origin.

If you do the opposite :

  • You translate your ship. Its center is now at 10 units of the origin
  • You scale your ship. Every coordinate is multiplied by 2 relative to the origin, which is far away... So you end up with a big ship, but centered at 2*10 = 20. Which you don't want.

Does that make sense ?

(Source: opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/)