Search code examples
c++openglrotationglfwglm-math

Object rotation using keys


I want to rotate a cube using keys. This is a part of the code. When I press LEFT key, cube rotates to left, etc. My goal is to rotate cube all around, so I have to rotate it by x and y axis which causes a problem.

I have defined mat4 rotation; and used it to assign a rotation when I press and hold a key. When I hold the key, it is rotating, for example to left. Then I release the key and the object gets back to initial position (camera gets back to initial position, since object is not moving). I think this problem is causing the auto rotateMat = rotation; line which is defined below the key functions. What am I doing wrong?

    mat4 rotation; //global 

    if(keysPressed[GLFW_KEY_LEFT]){
                timer -= delta;
                rotation = rotate(mat4{}, timer * 0.5f, {0, 1, 0});
    }

    if(keysPressed[GLFW_KEY_RIGHT]){
                timer += delta;
                rotation = rotate(mat4{}, timer * 0.5f, {0, 1, 0});
    }

   if(keysPressed[GLFW_KEY_UP]){
                timer += delta;
                rotation = rotate(mat4{}, timer * 0.5f, {1, 0, 0});
   }

   if(keysPressed[GLFW_KEY_DOWN]){
                timer -= delta;
                rotation = rotate(mat4{}, timer * 0.5f, {1, 0, 0});
   }

   ...
   program.setUniform("ModelMatrix", rotation* cubeMat); 
   cube.render();

UPDATE:

So the problem to this was solved when I used matrix variable as global variable, not local.


Solution

  • There are multiple ways how such an interaction can be implemented. One of the easier ones is to create a relative translation in every frame instead of a global one and add it to the current rotation:

    For this, one has to store the sum of all rotations in a global varialbe

    //Global variable
    mat4 total_rotate;
    

    And calculate the relative translation in every frame:

    //In the function
    mat4 rotation;
    
    if(keysPressed[GLFW_KEY_LEFT]){
                rotation = rotate(mat4{}, delta, {0, 1, 0});
    }
    
    if(keysPressed[GLFW_KEY_RIGHT]){
                rotation = rotate(mat4{}, -delta, {0, 1, 0});
    }
    
    if(keysPressed[GLFW_KEY_UP]){
                 rotation = rotate(mat4{}, delta, {1, 0, 0});
    }
    
    if(keysPressed[GLFW_KEY_DOWN]){
                 rotation = rotate(mat4{}, -delta, {1, 0, 0});
    }
    
    total_rotate = total_rotate * rotation;
    ...
    program.setUniform("ModelMatrix", total_rotate * cubeMat); 
    cube.render();
    

    As an alternative, you could store the two rotation angles instead and calculate the matrix in every frame:

    //Global variables
    float rot_x = 0.0f, rot_y = 0.0f;
    
    //In every frame    
    if(keysPressed[GLFW_KEY_LEFT]){
                rot_x += delta;
    }
    
    if(keysPressed[GLFW_KEY_RIGHT]){
                rot_x -= delta;
    }
    
    //Same for y
    
    auto rotation = rotate(rotate(mat4{}, rot_y, {0, 1, 0}), rot_x, {1, 0, 0}
    ...
    program.setUniform("ModelMatrix", rotation * cubeMat); 
    cube.render();