Search code examples
c++openglmatrixglm-math

Clear a scale component from view matrix. Camera-independent scaling


I need for my little program to scale a gizmo by camera distance to conveniently move objects at anytime. I think I have two options:

  1. Calculate distance from gizmo to camera, make a matrix for scaling, multiply all points in cycle:

    glm::mat4 scaleMat;
    scaleMat= glm::scale(scaleMat, glm::vec3(glm::distance(cameraPos,gizmoPos)));
    
    for (int i = 0; i < vertices.size(); i++)
    {
        vertices[i] = glm::vec3(scaleMat * glm::vec4(vertices[i], 1.0));
    }
    
  2. Clear the scale component of the view (lookAt) matrix only for gizmo.

If I use the first way my scale of gizmo accumulates the scale and increase size of gizmo any time when I change camera position. I think the second way is more accurate, but how to do that? Thank you!


Solution

  • If you want to apply different scaling each time to the same model, you should not manipulate vertexes (you should never do, in fact), but the Model Matrix. Through that you can manipulate the object without processing the vertexes via code. I would go with something like this:

    glm::mat4 modelMatrix(1.0f);
    modelMatrix = glm::scale(modelMatrix,glm::vec3(glm::distance(cameraPos,gizmoPos)));
    

    This will give you the scaled Model View matrix. Now you only need to pass it to your Vertex Shader.

    You should have, roughly, something like this:

    #version 330 core
    
    // Input vertex data, different for all executions of this shader.
    layout(location = 0) in vec3 vertexPosition_modelspace;
    
    uniform mat4 M;
    
    void main(){
        gl_Position =  M * vec4(vertexPosition_modelspace,1);
    }
    

    I have not tested the code but it is really similar to the code of one of my projects. There I keep my model matrix so the scaling is accumulated, but if you pass to the vertex shader a brand new matrix each time, nothing will be remembered.

    If you need more about passing the uniform to the shader, have a look here at my current project's code.

    You can find the scaling inside TARDIS::applyScaling and the shader loading in main.cpp