1

I'm working on a FPS style camera to fly around my 3D scene using OpenGL. I'm using GLM for the mathmetics and I calculate a direction vector with a glm::rotate on the x-axis and the y-axis using mouse movements. I have a static up vector since I'm fine with strafing on the horizontal axis and don't really need any rolls.

However, when I move forward towards the negative z direction and I eventually reach the center point of the scene (z=0) the vertical camera flips (y direction). Moving the mouse downwards will now result in an upward motion. The direction vectors are calculated like they should so I'm guessing it has something to do with how glm::lookAt calculates its view Matrix?

Here is the relevant code:

// Player movement
glm::vec3 position(0.0f, 0.0f, 5.0f);
glm::vec3 direction(0.0f, 0.0f, -1.0f);
glm::vec3 up(0.0f, 1.0f, 0.0f);
float speed = 0.05f;
bool warped = false;
...

void render()
{
    ...
    view = glm::lookAt(position, position + direction, up); 
    glUniformMatrix4fv(glGetUniformLocation(basicShader.shaderProgram, "view"), 1, GL_FALSE, glm::value_ptr(view));
    ...    
}


void handleKeyboard()
{
    float speed = 0.05f;
    if(keys['w'])
        position += speed * direction;
    if(keys['s'])
        position -= speed * direction;
    if(keys['a'])
        position -= speed * glm::cross(direction, up);
    if(keys['d'])
        position += speed * glm::cross(direction, up); 
    if(keys['q'])
        exit(1);
}

// Set with following callbacks:
// glutMotionFunc(mouse);
// glutPassiveMotionFunc(mouse);
void mouse(int x, int y)
{  
    if(!warped)
    {
        float mouseSensitivity = 15.0f;

        float horizontal = (width / 2) - x;
        float vertical = (height / 2) - y;

        horizontal /= mouseSensitivity;
        vertical /= mouseSensitivity;

        direction = glm::rotate(direction, horizontal, glm::vec3(0.0f, 1.0f, 0.0f));
        direction = glm::rotate(direction, vertical, glm::vec3(1.0f, 0.0f, 0.0f));

        warped = true;
        glutWarpPointer((width / 2), (height / 2));
    }
    else
        warped = false;
}
genpfault
  • 51,148
  • 11
  • 85
  • 139
Joey Dewd
  • 1,804
  • 3
  • 20
  • 43

1 Answers1

4

I'm not entirely sure what the problem is, but when I use LookAt for an FPS cam I also include a forward unit vector.

E.g (copied relevant segments from some code I have) - using quaternions (orientation), but I'm sure matrices will have the same result)

static glm::vec3 defaultUpVector() { return glm::vec3(0, 1, 0); }
static glm::vec3 defaultForwardVector() { return glm::vec3(0, 0, -1); }

pUpVector = defaultUpVector() * orientation;
pLookAt = position + (defaultForwardVector() * orientation);
pView = glm::lookAt(position, pLookAt, pUpVector);

upvector and lookat are both vec3, and view is mat4

Hope this helps.

EDIT: I notice you are using a direction, so I would probably look at where you use rotate.

This will set the quat for an FPS cam with no roll

pLocalOrientation = 
    glm::angleAxis(pLocalEularAngles.x, glm::vec3(1, 0, 0)) *
    glm::angleAxis(pLocalEularAngles.y, glm::vec3(0, 1, 0));

pLocalOrientation == orientation (for the example)

If you decide to use quats.

Rebirth
  • 478
  • 1
  • 4
  • 13
  • I like the idea and tried to see if a forward vector would solve my problems but didn't unfortanetly, as far as I can see my rotation is oké. Everything works perfecly except the flip. Direction vector is the same even after the flip. I haven't started on quaternions yet so that is a no go for now :) – Joey Dewd Jul 23 '13 at 16:41
  • I recommend quats for these purposes. (pLocalOrientation = glm::quat(glm::radians(pRotationIncr)) * pLocalOrientation;) - will do 6dof if you ever needed it. pRotationIncr = amount rotated in the frame (vec3). – Rebirth Jul 23 '13 at 16:46
  • I know, from what I've heard Quaternions seem to eliminate all the problems Matrix and eular angles have and with less code (AFAIK) and I will eventually start learning these but at the moment I'm learning OpenGL and I will learn it one step at the time :) Quats is for later ;) It's not like it's impossible to get a decent FPS camera, I just have one strange bug :) – Joey Dewd Jul 23 '13 at 16:49
  • If you are working with only two axis, then have you tried using sine and cosine methods? It may help you learn what is going on without relying on glm math. It isn't difficult, and I think Nehe has an old tutorial on it. – Rebirth Jul 23 '13 at 16:54
  • Yeah, I'm aware of the sine and cosine methods :) – Joey Dewd Jul 23 '13 at 17:10