Moving and looking around with camera conflicts

880 views Asked by At

I am using GLFW to render some things in OpenGL. I created a Camera class that allows movement and looking around with the camera. These work fine when being done alone, but when they are used together, the following things happen:

When moving the camera forward, the rotation becomes slow and rotation resets the camera to the original position.

When moving the camera backwards, left, or right, the rotation causes everything to go out of the picture. The only things that I am rendering right now are two triangles directly in front of the camera, so I don't know what the camera ends up looking at. It will also occasionally reset the camera position like above, but only after moving forward first.

The code is relatively simple and the entire source is here, mainly in the Camera, Entity, and main source and header files, but I will also include the relevant bits below.

This is the function that I'm setting for GLFW's key callback and deals with movement:

void keyCallback(GLFWwindow * window, int key, int scancode, int action, int mods)
{
    switch(key)
    {
        case GLFW_KEY_W:
            cam->move(glm::vec3(0.0, 0.0, -0.05));
            break;
        case GLFW_KEY_S:
            cam->move(glm::vec3(0.0, 0.0, 0.05));
            break;
        case GLFW_KEY_A:
            cam->move(glm::vec3(-0.05, 0.0, 0.0));
            break;
        case GLFW_KEY_D:
            cam->move(glm::vec3(0.05, 0.0, 0.0));
            break;
        case GLFW_KEY_ESCAPE:
            glfwSetWindowShouldClose(window, GL_TRUE);
            break;
        default:
            break;
    }
}

This is the function dealing with mouse movement and looking around with the camera:

void cursorMoveCallback(GLFWwindow * window, double xpos, double ypos)
{
    printf("Mouse Moved to (%f, %f)\n", xpos, ypos);

    // Change camera angle
    glm::vec3 cameraMovement;

    // Change in x (rotation about y axis)
    if(xpos > 0)
        cameraMovement.x = -0.0005;
    else if (xpos < 0)
        cameraMovement.x = 0.0005;

    // Change in y (rotation about x axis)
    if(ypos > 0)
        cameraMovement.y = 0.0005;
    else if(ypos < 0)
        cameraMovement.y = -0.0005;

    // Reset Cursor position
    glfwSetCursorPos(window, 0, 0);


    // Change Position of Camera
    cameraMovement += Camera::getCurrentCamera()->getDirection();
    Camera::getCurrentCamera()->setDirection(cameraMovement);
}

Moving Camera:

glm::vec3 Camera::move(glm::vec3 translation)
{
    int dims = viewMatrix.length() - 1;
    // Apply translation
    for (int i = 0; i < dims; i++)
        viewMatrix[dims][i] -= translation[i];

    // Update viewMatrix
    Program::updateViewMatrix(viewMatrix);

    return Entity::move(translation);
}

glm::vec3 Entity::move(glm::vec3 translation)
{
    // Move by amount
    position += translation;

    // Return new position
    return position;
}

Looking with camera:

glm::vec3 Camera::setDirection(glm::vec3 newDirection)
{
    viewMatrix = glm::lookAt(newDirection, position, glm::vec3(0.0, 1.0, 0.0));

    Program::updateViewMatrix(viewMatrix);

    return Entity::setDirection(newDirection);
}

glm::vec3 Entity::setDirection(glm::vec3 newDirection)
{
    // Set direction of entity
    direction = newDirection;

    // Return new direction of entity
    return direction;
}

The Program::updateViewMatrix() call just goes through all active OpenGL programs and sets uniforms for the view matrix. Please let me know if there could be any other relevant code that would make a difference.

My guess would be that I'm running into some sort of threading issue due to the callbacks or there's an issue with trying to both move and look around at the same time.

UPDATE 1: I have fixed the order of arguments to glm::lookAt(). This fixes the disappearing issue, but after moving any, the rotation seems to be slower than it should.

2

There are 2 answers

0
BDL On BEST ANSWER

The problem is that glm::lookAt(eye, center, up) expects other parameters than you supply:

  • eye is the position of the camera in space
  • center is the point where the camera looks at. Important: This is a position, not a direction
  • up is the up vector, which is a direction.

For more details one might find this post very useful.

1
datenwolf On

You should set uniform values right before you need them, i.e. in the drawing code, before making the glDraw… calls. If you set them somewhere in the event handlers, anything happening between the event handler and drawing may overwrite the values you put there. This is what happens to you: Your both camera class instances write to the same location and only one of them can win.