Camera movement

I am trying to write a program that will allow the user to rotate the camera in any direction and then to ‘walk’ in that direction. I am using quaternions to avoid the problem of gimble lock. Everything works fine - you can look in any direction and the view changes correctly, but the problem is that when you try to walk forward, you always head in the direction that you were facing originally (i.e. If you turn 90 degrees to the left and try to move forward, you will slide to the right).

I am storing the camera’s position as a vector in an array (x, y, z). Here is a slice of my code:

if (DomScene.GetKey(VK_UP))
DomScene.cameraPos[2] -= 1;

if (DomScene.GetKey(VK_DOWN))
DomScene.cameraPos[2] += 1;

if (DomScene.GetKey(VK_LEFT))
DomScene.cameraYaw -= 1;
DomScene.keyY = -1;

if (DomScene.GetKey(VK_RIGHT))
DomScene.cameraYaw += 1;
DomScene.keyY = 1;

I know that I need to add something along the lines of:

DomScene.cameraPos[0] += (float)(sin(DomScene.cameraYawpiover180) * 1.0f);
DomScene.cameraPos[1] += (float)(sin(DomScene.cameraPitch
piover180) * 1.0f);
DomScene.cameraPos[2] += (float)(cos(DomScene.cameraYaw*piover180) * 1.0f);

for ‘up’ and:

DomScene.cameraPos[0] -= (float)(sin(DomScene.cameraYawpiover180) * 1.0f);
DomScene.cameraPos[1] -= (float)(sin(DomScene.cameraPitch
piover180) * 1.0f);
DomScene.cameraPos[2] -= (float)(cos(DomScene.cameraYaw*piover180) * 1.0f);

for ‘down’ - but this code makes you move at wierd angles.

Can anyone help?

I use different words for the angles, the ones I’m used to. Heading is when you turn your head left/right (maybe that’s yaw in your code), pitch is when you look up/down. Just to make sure you understand the meanign of my words.

So, first we create some direction vector. First the basic direction in the XZ-plane. That is, turing left/right only.

dir.x = cos(heading);
dir.z = sin(heading);

The code assumes that positive Y is up, and 0 degrees is along the positive X axis, with increasing angle towards the positive Z axis.

Then, we implement up/down. 0 degrees is stright forward. 0 to 90 degrees is upwards, 90 being stright up. 0 to -90 degrees is downwards, -90 being stright down.

dir.x = cos(heading) * cos(pitch);
dir.z = sin(heading) * cos(pitch);
dir.y = sin(pitch);

Now you will have a unit vector, pointing in the direction formed by the heading and pitch angle. To move in that direction, just do a component wise addition with the current position.

With a piece of paper, and a pencil, you will see that it’s not that hard to come up with the trigonometry needed, assuming you know your trigonometry, which you should if you want to do 3D programming.

The camera’s position is in world space, so the values for the movement should also be in world space-- your fix is correct, in theory. On the other hand…

…you have not fixed the gimble lock problem (regardless of your use of quaternions) because you are still using Euler angles to keep track of the camera’s orientation.