2
votes

I'm implementing a first person camera using the GLM library that provides me with some useful functions that calculate perspective and 'lookAt' matrices. I'm also using OpenGL but that shouldn't make a difference in this code.

Basically, what I'm experiencing is that I can look around, much like in a regular FPS, and move around. But the movement is constrained to the three axes in a way that if I rotate the camera, I would still move in the same direction as if I had not rotated it... Let me illustrate (in 2D, to simplify things).enter image description here

In this image, you can see four camera positions. Those marked with a one are before movement, those marked with a two are after movement. The red triangles represent a camera that is oriented straight forward along the z axis. The blue triangles represent a camera that hasbeen rotated to look backward along the x axis (to the left). When I press the 'forward movement key', the camera moves forward along the z axis in both cases, disregarding the camera orientation.

What I want is a more FPS-like behaviour, where pressing forward moves me in the direction the camera is facing. I thought that with the arguments I pass to glm::lookAt, this would be achieved. Apparently not.

What is wrong with my calculations?

// Calculate the camera's orientation
float angleHori = -mMouseSpeed * Mouse::x; // Note that (0, 0) is the center of the screen
float angleVert = -mMouseSpeed * Mouse::y;

glm::vec3 dir(
    cos(angleVert) * sin(angleHori),
    sin(angleVert),
    cos(angleVert) * cos(angleHori)
);

glm::vec3 right(
    sin(angleHori - M_PI / 2.0f),
    0.0f,
    cos(angleHori - M_PI / 2.0f)
);

glm::vec3 up = glm::cross(right, dir);

// Calculate projection and view matrix
glm::mat4 projMatrix = glm::perspective(mFOV, mViewPortSizeX / (float)mViewPortSizeY, mZNear, mZFar);
glm::mat4 viewMatrix = glm::lookAt(mPosition, mPosition + dir, up);
2

2 Answers

1
votes

gluLookAt takes 3 parameters: eye, centre and up. The first two are positions while the last is a vector. If you're planning on using this function it's better that you maintain only these three parameters consistently.

Coming to the issue with the calculation. I see that the position variable is unchanged throughout the code. All that changes is the look at point I.e. centre only. The right thing to do is to first do position += dir, which will move the camera (position) along the direction pointed to by dir. Now to update the centre, the second parameter can be left as-is: position + dir; this will work since the position was already updated to the new position and from there we've a point farther in dir direction to look at.

0
votes

The issue was actually in another method. When moving the camera, I needed to do this:

void Camera::moveX(char s)
{
    mPosition += s * mSpeed * mRight;
}

void Camera::moveY(char s)
{
    mPosition += s * mSpeed * mUp;
}

void Camera::moveZ(chars)
{
    mPosition += s * mSpeed * mDirection;
}

To make the camera move across the correct axes.