title: OpenGL multiple matrix transormations
body: <p>I have simple vertex shader for models</p>
  
  <pre><code>#version 330
  
  layout(location = 0) in vec3 VertexPosition;
  layout(location = 1) in vec3 VertexNormal;
  layout(location = 2) in vec2 VertexUV;
  
  out VS_GS_VERTEX
  {
      vec3 vs_worldpos;
      vec3 vs_normal;
      vec2 VertexUV;
  } vertex_out;
  
  uniform mat4 modelMatrix;
  uniform mat4 projectionMatrix;
  uniform mat4 lookAtMatrix;
  
  void main(void)
  {
      mat4 MVP = projectionMatrix * lookAtMatrix * modelMatrix;
  
      gl_Position = MVP * vec4(VertexPosition, 1.0);
      gl_Normal = mat3(modelMatrix) * VertexNormal;
  
      vertex_out.vs_worldpos = gl_Position.xyz;
      vertex_out.vs_normal = gl_Normal;
      vertex_out.VertexUV = VertexUV;
  }
  </code></pre>
  
  <p>and I pass there modelMatrix</p>
  
  <pre><code>  modelMat := MatrixMultiply(transMat, baseMat);
    modelMat := MatrixMultiply(modelMat, scaleMat);
    modelMat := MatrixMultiply(modelMat, rotMat);
    glUniformMatrix4fv(modelMatrix_loc, 1, false, @modelMat);
  </code></pre>
  
  <p>where transMat for positioning, scaleMat to enlarge whole picture and rotMat to rotate whole terrain.
  <img src="https://i.stack.imgur.com/NF1Yr.jpg" alt="without scale">
  Everything fine while baseMat is coordinates of model on terrain</p>
  
  <pre><code>baseMat := CreateTranslationMatrix(AffineVectorMake(pos.x, pos.y, pos.z));
  </code></pre>
  
  <p>but when I trying also to enlarge model by own model's scale (model have zero based coordinates, for example roots of tree at (0, 0, 0))</p>
  
  <pre><code>  scMat := CreateScaleMatrix(AffineVectorMake(scale, scale, scale));
    trMat := CreateTranslationMatrix(AffineVectorMake(pos.x, pos.y, pos.z));
  
    baseMat := MatrixMultiply(scMat, trMat);
  </code></pre>
  
  <p><img src="https://i.stack.imgur.com/XX5rO.jpg" alt="with model&#39;s scale"></p>
  
  <p>models not just enlarged, they also changing coordinates and not placed on terrain anymore.
  Is it possible to make one model matrix with model's scaling, rotation, translation, yet another translation, scaling and rotation? Or I should do something else? Matrix math from <code>GLScene</code> and seems works fine.</p>
  
  <p><strong>Edit</strong>: I can't use <code>proper order</code> with matrices by scaling first because I have this</p>
  
  <p><img src="https://i.stack.imgur.com/tRKJ9.jpg" alt="scaling image">
  <img src="https://i.stack.imgur.com/y9dG3.jpg" alt="scaling more"><br>
  The structure of terrain is tiles of 64x64 chunks, each have base coordinates. So to put it together I need first to translate each chunk to proper position and only then scale to enlarge image and rotate with mouse.
  Each model also have absolute position assigned to terrain. I should scale and rotate model (own model's modifiers) and put it to proper position on terrain. <code>transMat</code> (to put tiles and models at the center of screen), <code>scaleMat</code> and <code>rotMat</code> shared for both terrain and models. But local <code>scMat</code> and <code>trMat</code> are for enlarge model and put it to right place.</p>
  
  <p>If I leave terrain working as is with <code>rotMat * scaleMat * transMat</code> but using models as <code>rotMat * transMat * trMat * scaleMat * scMat</code> I have this
  <img src="https://i.stack.imgur.com/3yzPg.jpg" alt="models"><br>
  a bit closer<br>
  <img src="https://i.stack.imgur.com/LD8QS.jpg" alt="1 meter closer"></p>
  
  <p><strong>Edit2</strong>: changed vertex shader to</p>
  
  <pre><code>uniform mat4 modelMatrix;
  uniform mat4 MVP;
  
  void main(void)
  {
      vec4 modelPos = modelMatrix * vec4(VertexPosition, 1.0);
      gl_Position = MVP * modelPos;
      gl_Normal = mat3(modelMatrix) * VertexNormal;
  
      vertex_out.vs_worldpos = gl_Position.xyz;
      vertex_out.vs_normal = gl_Normal;
      vertex_out.VertexUV = VertexUV;
  }
  </code></pre>
  
  <p>and passed </p>
  
  <pre><code>modelMatrix = modelRotMat * modelScaleMat;
  mvpMatrix = projMat * lookAtMat * rotMat * scaleMat * modelTransMat * transNat;
  </code></pre>
  
  <p>now it works as expected, thanks for help.</p>