# Thread: How to properly move/strafe/yaw/pitch camera in OpenGL/GLUT using gluLookAt?

1. ## How to properly move/strafe/yaw/pitch camera in OpenGL/GLUT using gluLookAt?

Hi,

Math is not my strong suite and for the code below I searched a lot and this is what I was able to achieve, there's still a few issues that I can't seem to fix.

My camera is setup like this:
Code:
`gluLookAt(eyeX, eyeY, eyeZ, eyeX + refX, eyeY + refY, eyeZ + refZ, 0.0f, 1.0f, 0.0f);`
And this is my current code to move the camera:
Code:
```void setCameraEye(int transformation, int direction) {
switch(transformation) {
case CAMERA_MOVE:
eyeX += direction * sin(angleYaw) * MOVE_SPEED;
eyeY += direction * sin(anglePitch) * MOVE_SPEED;
eyeZ += direction * -cos(angleYaw) * MOVE_SPEED;

break;
case CAMERA_STRAFE:
eyeX += direction * sin(angleYaw + PI/2) * MOVE_SPEED;
eyeZ += direction * -cos(angleYaw + PI/2) * MOVE_SPEED;

break;
case CAMERA_ELEVATE:
eyeY += direction * sin(anglePitch + PI/2) * MOVE_SPEED;
eyeZ += direction * -cos(angleYaw + PI/2) * MOVE_SPEED;

break;
case CAMERA_PITCH:
anglePitch += direction * ROTATE_SPEED;

refY = tan(anglePitch);

break;
case CAMERA_YAW:
angleYaw += direction * ROTATE_SPEED;

refX = sin(angleYaw);
refZ = -cos(angleYaw);

break;
}
}```
All angles and camera points are floats.

Camera movement, strafe and elevation seems to be working just fine, yaw works too. I can even STRAFE and YAW around an object completing a 360º circle; camera moving in the XZ plane.

VIDEO DEMO (FLASH): Play - ShowMeWhatsWrong.com (You can see that it works fine)

My problem is that I want to do the same but MOVE and PITCH around the object completing a 360º circle, just as I can do with STRAFE/YAW. But it's not working, when I'm looking above -90º down or above 90º up the object I'm looking at disappears.

VIDEO DEMO (FLASH): Play - ShowMeWhatsWrong.com (You can see that when the angle is above -1.57 ~ 90º, the object disappears)

So...

Question 1)
How can I solve this MOVE/PITCH problem? Any easy solution?

Question 2)
Do you think there's something wrong my code? Specially the sine, cosine and tangent functions with those specific axis? I found lots of different implementations on the Web, this ones seems to produce the best (and correct?) results as far as I can tell.

2. "gluLookAt" exists so that one doesn't need to worry about pitch/yaw/roll! If you want to use them explicitly, use "glRotatef"/"glRotated".

EDIT: To move the camera, grab the appropriate vectors from the modelview matrix:
Code:
```float mat[16];

glGetFloatv(GL_MODELVIEW_MATRIX, mat);```
mat[0], mat[4], mat[8] is the right vector
mat[1], mat[5], mat[9] is the up vector
mat[2], mat[6], mat[10] is the forward vector ( looking towards the screen )

EDIT^2: You should first use gluLookAt or glRotatef of course.

3. I would rather use gluLookAt for now as I have most of the code working.

If you (or anyone) could help me solve the problem with my current code, I would be much appreciated.

4. I would rather use gluLookAt for now as I have most of the code working.
That is nice but that is not the correct way to create a camera in any API. LookAt is a special type of matrix that can be used for fly by views, views that target one object, and tutorials that always look at 0,0,0. A true camera will make use of a look at but not for first person camera. You could translate your camera to the object it is attached to, translate back by the negative look vector and then perform a look at for a third person camera but it would be pointless since what I just described does the same thing.

5. Why is there countless of posts around the web about using gluLookAt to achieve the same thing then? Actually, I barely can find any information on what to do you without it, everything I find is using gluLookAt.

6. Why is there countless of posts around the web about using gluLookAt to achieve the same thing then?
Maybe they are wrong or they are using a different camera? Do you really want to go down this path of arguing with us? Most of us have implemented cameras time and time again. Perhaps you ought to listen to some of the others here.

For a camera you need an up, right and look vector. You can either use axis-angle rotations or quaternions. Yaw is a rotation about the up axis, pitch is a rotation about the x axis, and roll is a rotation about the z axis. For a quaternion camera you can extract the up, right, and look vectors from the view matrix - but that has already been mentioned in this thread so I won't get into it.

7. I'm not arguing, it's a question, maybe you should look that up in the dictionary. Geez, why are you people so harsh...

Forget I asked anything.

8. You asked a question.
Several people responded to it.
You did not listen to or like the answer.
You insist on doing it your way which is incorrect.

That is why I'm being so harsh.

So just for fun let's go down your road for a moment and use gluLookAt for all cameras. I do not use OpenGL but a camera is a camera regardless of API. What exactly are you going to 'look at', what is the eye point, and what is the up vector you will use? Are you going to use the world up vector or some other up vector? Whichever one you choose will make a huge difference in how the camera behaves.

The idea is that lookAt assumes you know what you are looking at but sometimes you do not know what the camera is looking at. The up, right, and look vectors solve this problem. So let's say you have a first person camera in the world and the player wants to yaw to the left by moving the mouse. What is the camera looking at now? You do not have that information and therefore gluLookAt will do nothing for you. Notice an identity matrix here:

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Notice the up, right and look vectors:
Right - 1 0 0
Up - 0 1 0
Look - 0 0 1

So the default view matrix is the identity matrix which essentially means the camera has no rotation about any axes and is looking down the z axis (depending on your specific coordinate system).

You are also using sin and cos in your camera which will only work for specific types of cameras which are FPS cameras. Yet you also insist on gluLookAt which does not work for first person cameras. Sin and Cos do not need to be used in any camera code b/c you can opt for using quaternions or axis-angle rotations which only require the angle of rotation about a specified axis. Both axis-angle rotations and quaternion rotations are the equivalent of taking a toothpick and sticking into a golfball and rotating the golfball around the toothpick. Other forms of rotation often attempt to rotate only around the 3 cardinal axes which ends up gimbal locking.

The correct way to implement a camera is to use an up, right, and look vector or use quaternions and extract the up, right, and look vector from the resulting matrix. Strafing is moving along the right vector (pos or neg), flying is moving along the up vector (pos/neg) and walking (pos/neg) is moving along the look vector. As the camera moves these vectors are oriented so that they match the orientation of the camera and not necessarily those of the world. With quaternion cameras you can also easily spherically linearily interpolate (SLERP) between two orientations and or perform spherical quadrangle interpolation or SQUAD.

Once you get your camera code working you can actually create an orientation class from it that will correctly orient your 3D objects in 3D space. However I will leave that as an exercise for you to do once you get your camera working.

The purpose of this board is to assist you by guiding you in the right direction. If we simply solve the problem for you then we have done you a huge injustice and you will not learn anything. Now if someone is so nice as to provide code then so be it but most of us would rather help people with the fundamentals and then allow them to synthesize the code IE: figure out the implementation of the solution. Now if you are ready to listen to others when they provide valuable feedback instead of insisting on your way which obviously does not work or you wouldn't be asking the question in the first place then I think several members here can help you a great deal. There are some very intelligent, talented, and experienced programmers on these boards and you would do well to listen to them.

9. Originally Posted by Bubba
You asked a question.
Several people responded to it.
You did not listen to or like the answer.
You insist on doing it your way which is incorrect.
Why are you assuming all that just because I made a question? And where did I insisted on doing it my way? I didn't insist in anything. This is a discussion board, people ask questions and other people responds to them, when people asking the questions are still confused or don't understand something, they ask again. That's how it works, that's how normal people behave.

Why should I just take your (or anyone's) answer without understanding them? Cause that's exactly what you're saying.

Originally Posted by Bubba
That is why I'm being so harsh.
That's not a reason, if you don't want to answer, then don't. I never criticized or said you (or anyone) was wrong. How could I? I'm new at this... I just made a a few simple questions, because, well, I was still confused about a few things.

Also, another two things:
1) Maybe, just maybe, have you ever thought I could have a really strong reason for wanting to use gluLookAt instead of any other means? But now I'm not even going to bother explaining why. You're rude and that was uncalled for.
2) It doesn't matter if people are 110% right, I want to understand the why before taking a decision instead of just doing what I'm told. I don't know you, you can be right but you can be wrong. Wither way, I have to take you word for it, no matter if you are wrong or right, so excuse me for asking more questions and trying to understand things.

Originally Posted by Bubba
So just for fun let's go down your road for a moment and use gluLookAt for all cameras. I do not use OpenGL but a camera is a camera regardless of API. What exactly are you going to 'look at', what is the eye point, and what is the up vector you will use? Are you going to use the world up vector or some other up vector? Whichever one you choose will make a huge difference in how the camera behaves.
I only have ONE camera and I thing that makes a difference in how you look at a problem. I don't think I have to care about all those things, but I never explained what I was trying to do anyway. Nothing fancy, I just wanted to have one single camera I could move in space, that's all.

Originally Posted by Bubba
The idea is that lookAt assumes you know what you are looking at but sometimes you do not know what the camera is looking at. The up, right, and look vectors solve this problem. So let's say you have a first person camera in the world and the player wants to yaw to the left by moving the mouse. What is the camera looking at now? You do not have that information and therefore gluLookAt will do nothing for you.
I'm not sure what you mean with all that, but if the camera is at (0,0,0) and I'm looking at (0,0,-1), if I yaw to the left, than the camera will be looking at something like (-a,0,-1-b). Where a and b are some values (which I believe would be negative, that's the reason for the minuses) that would be pointing to the new look at point.

It's like you put your hand in front of you and stretch your arm and you look at your hand all the time and start spinning, you'll always be looking at your hand. The only difference here is that you won't always have an object in front of you at that same distance, but you'll still be able to look before and after.

Originally Posted by Bubba
You are also using sin and cos in your camera which will only work for specific types of cameras which are FPS cameras. Yet you also insist on gluLookAt which does not work for first person cameras. Sin and Cos do not need to be used in any camera code b/c you can opt for using quaternions or axis-angle rotations which only require the angle of rotation about a specified axis. Both axis-angle rotations and quaternion rotations are the equivalent of taking a toothpick and sticking into a golfball and rotating the golfball around the toothpick. Other forms of rotation often attempt to rotate only around the 3 cardinal axes which ends up gimbal locking.
When and where did I specify I wanted to do an FPS camera? I only said I wanted a camera to move in space, that's it... I'm using sin and cos because that's the code I found on the web which seemed simple enough for me to understand, that's all.

Originally Posted by Bubba
The correct way to implement a camera is to use an up, right, and look vector or use quaternions and extract the up, right, and look vector from the resulting matrix.
Sure, and you can do that with gluLookAt as already found some working examples of such. Those vectors are there and I'm not sure it's using quaternions but I believe it is cause there are a bunch of calculations with all the vectors. But in the end, the camera position, look at point and the up vector are all changed by calling gluLookAt().

What's so wrong with that? If you "shouldn't" use gluLookAt, you do all those vectors calculations and then how do you setup the camera position, look at point and up/right vectors?

In the end, that's all I asked... Your answer could have been as simple as "you can't use sin/cos/whatever, you'll only have the camera you want by using quaternions". If you can do all that and avoid calling gluLookAt all, fine, but you can also do the exact same thing using that function, why is that so bad? Cause if I ever insisted in anything, it was only that.

Originally Posted by Bubba
The purpose of this board is to assist you by guiding you in the right direction. If we simply solve the problem for you then we have done you a huge injustice and you will not learn anything. Now if someone is so nice as to provide code then so be it but most of us would rather help people with the fundamentals and then allow them to synthesize the code IE: figure out the implementation of the solution.
I never asked anyone to solve anything for me. But you didn't help either because all you cared about was saying not to use gluLookAt and using something else. Which I still don't see where the problem cause you need to setup the camera somehow and that's the only way I know of. Sure, that function comes from GLU and there must be other ways to do it, but I have to use GLUT/GLU and yes, there are probably more ways to do it, but you were not clear on that, that's why I insisted on gluLookAt, also because every thread about subject probably has a call to this function somewhere and you tell me it's wrong? You can surely understand how that's confusing for some one knew on all this.

Originally Posted by Bubba
Now if you are ready to listen to others when they provide valuable feedback instead of insisting on your way which obviously does not work or you wouldn't be asking the question in the first place then I think several members here can help you a great deal. There are some very intelligent, talented, and experienced programmers on these boards and you would do well to listen to them.
Maybe you should listen too...

My way does not work because my way of calculating the camera movements and all that is wrong, not because I'm using gluLookAt, but you insisted on saying that that was the problem, when it clearly wasn't.

The only problem in my implementation is how the camera position and look at point are calculated and how all that can be used to move the camera in all directions without having problems like gimbal lock. It has nothing to do with the use of gluLookAt cause that function is only used to setup the camera position, look at point and up vector.

Try to understand where people come from next time and what exactly are they asking before jumping into so harsh responses, totally uncalled for.

This subject is now terminated on my end.

For all it's worth and where applied, thank you all.

10. Try to understand where people come from next time and what exactly are they asking before jumping into so harsh responses, totally uncalled for.
I know exactly where you are coming from. You have code that uses glLookAt and therefore want to use gluLookAt to do what you want. The sad fact is gluLookAt will not do what you want. gluLookAt can be used for many things but it is not ideal to use for a camera other than a look at camera or a flyby type camera.

In fact let's just pretend that you haven't read any tutorials on the internet and that gluLookAt doesn't even exist. So answer my question about yawing the camera left regardless of the world, what is in it, etc. How are you going to yaw the camera to the left. gluLookAt doesn't exist and if it did it still would not help b/c a camera can orient itself regardless of what is in the world. A camera is 3 orientation vectors which in turn produces a view matrix. This view matrix is used to render the scene. World * View * Projection where View is the view matrix for the current camera. Note that if this View is the identity matrix then the camera is at 0,0,0 with yaw of 0.0f, pitch of 0.0f, and roll of 0.0f looking down or up the z zxis depending on the 'handedness' of your coordinate system. The camera is not looking at 0,0,0 and it is not looking at any particular point in space - it is simply oriented in the manner I described.

What you need is a system that can rotate around an arbitrary axis and maintain 3 orthogonal unit vectors that always describe the orientation of the camera. Here are the rotations using axis angle rotations. Note that I've left the function definitions out b/c I'm a Direct3D fella and so my matrices are left-handed instead of right-handed and because you should be able to figure out what they do based on the function names.

Here is some sample incomplete code for a very simple axis-angle based camera.
Code:
```void Camera::Yaw(float units)
{
Matrix4x4 m;

if (m_cameraType == CAMERA_LAND)
{
//Account for FPS cameras here so that a yaw will not roll the camera
...
...
}
else
{
m = MatrixRotationAxis(&m_up,units);
}

// Transform vector by matrix, project result back into w = 1.0f
TransformVectorCoord(&m_right,&m);
TransformVectorCoord(&m_look,&m);
}

void Camera::Pitch(float units)
{
Matrix4x4 m;
m = MatrixRotationAxis(&m_right,units);

// Transform vector by matrix, project result back into w = 1.0f
TransformVectorCoord(&m_up,&m);
TransformVectorCoord(&m_look,&m);
}

void Camera::Roll(float units)
{
Matrix4x4 m;
m = MatrixRotationAxis(&m_look,units);

// Transform vector by matrix, project result back into w = 1.0f
TransformVectorCoord(&m_right,&m);
TransformVectorCoord(&m_up,&m);
}

const Matrix4x4 & Camera::GetViewMatrix() const
{
return m_viewMatrix;
}

void Camera::CalculateViewMatrix()
{
MakeOrthogonal();

if (m_viewMode = VIEW_TARGET)
{
// Use gluLookAt to compute view matrix
// Use world up vector as up, camera pos as at, and target pos as eye
}
else
{
// Set m_orbitRadius to 0.0f for FPS camera, else set to non-zero for third person camera
Vector3 pos = m_vecPos + m_look * m_orbitRadius;
...
m_viewMatrix[0] = ............
...
...
}
}

void Camera::Walk(float units)
{
m_vecPos += m_look * units;
}

void Camera::Strafe(float units)
{
m_vecPos += m_right * units;
}

void Camera::Fly(float units)
{
m_vecPos += m_up * units;
}

void Camera::MakeOrthogonal()
{
m_look = Normalize(&m_look);
m_up = Cross(&m_look,&m_right);
m_right = Cross(&m_up,&m_look);

m_up = Normalize(&m_up);
m_right = Normalize(&m_right);
}
...
...```
That should be enough to get you started. I also have a quaternion camera and orientation class but it is heavier on the math. The code is actually simpler but the math is far more complex. Several people on this forum or other forums can help you with a quaternion camera.

Once you get this done you will have a camera that can orient itself regardless of the world around it and move it freely through that world without having to focus on one specific 3D point or object - that is unless your camera is in target or flyby mode in which case it must have a target point or object.

An RTS camera is similar to this except that when you move you do not want to move on Y and you may need 3 more vectors to represent the orientation of the motion of the camera.

Also be extremely careful when looking at tutorials. They often gloss over important details that may not be important to the tutorial but are extremely important to you if you want to integrate their code into a larger system. The devil is always in the details and those details can leave you wandering out in the weeds for days or weeks. Also tutorials are normally geared towards showing one effect or technique and do not give you the bigger picture. They may load textures, meshes, sounds, etc. will nilly with no thought for memory management and this just cannot be done in a larger system without some serious consequences. They also tend to hide gotchas caused by their approach to the problem which is usually the brute force approach which is almost always incorrect.
Tutorials are good but they won't get you all that far. You will need read books and white papers from Siggraph as well as articles from GDC, Gamasutra, and/or Gamedev to really begin to understand what is going on under the hood. Once you figure that out you will need to read books about game and engine design in order to get all that 'stuff' working in a larger system. I think you will find it is impossible to code even a small graphical game without some type of framework holding it all together.

11. Actually no, you have no idea where I'm coming from nor my reasoning behind gluLookAt and since your insisting that you know what I want/need better than me, I'm not going to feed any more of this discussion.

But let me ask you one thing, what exactly is this for:
Code:
```if (m_viewMode = VIEW_TARGET)
{
// Use gluLookAt to compute view matrix
// Use world up vector as up, camera pos as at, and target pos as eye
}```
?

Why are you telling me to use gluLookAt now when you've arguing against it all along?

12. Err...

Take a look at the if statement.
Now read post #4.
Now take a look at the if statement again.
Now read post #4 again.
Do this until you understand...

13. gluLookAt and since your insisting that you know what I want/need better than me,
Cameras are cameras no matter what your needs are. They produce a view matrix and there are not really that many variations on cameras out there.

Do you really want to continue to argue with me or do you want to learn something here? We can do this all day or we can move on and help you with the issue at hand. I was harsh earlier b/c I picked up on this exact attitude in your earlier posts and now you are simply proving my hunch that you think you know what you are doing when you do not. If you insist that other tutorials are using gluLookAt then use those tutorials. It was my assumption those tutorials only took you so far and thus that is why you came here. Perhaps I'm incorrect in that assumption.

If you ask for help and do not listen then do not expect people to help you very often. Sipher had a very good post and you simply blew it off saying you want to use gluLookAt. gluLookAt is only part of the bigger picture.

gluLookAt could be used for:
• The fly-by camera view in Microsoft FSX
• The outside fly-by trackside view in RailWorks 2 (press 4 for this view)
• The flyby view in IL2 1946 (press F3)
• The control tower view in Microsoft FSX
• The spectator view of the race in GRID
• The spectator view of the race in EA's Nascar SimRacing
• The spectator view of the race in rFactor
• The jump-cam views in Need For Speed Undergound 1, 2, and Most Wanted
• The car crash cam view in Burnout Paradise
• Some of the outside stationary camera shots in GTA 3, GTA Vice City, GTA San Andreas, and GTA 4.
• The dunk and replay cameras in NBA 2K11 and NBA 2K10. They focus on one specific player.

gluLookAt could also be used to:
• Orient a turret so that it faces its target - within the motion constraints of the turret. There may be no valid orientation for a turret to face its target.
• Orient a spacecraft, aircraft, or other object to face another object.
• Orient a spacecraft, aircraft, or other object to face toward it's next waypoint in 3D space.
• Orient a player to face another player or enemy.
• Orient a player's head to track another object like a doorknob when opening a door - E: inverse kinematics

Note that the glulookAt will calculate the correct matrix but snapping to this orientation would be very unnatural and herky jerky. This may be fine for instantly switching camera views from an FPS mode or third person mode to fly by mode or tracking mode but it is not fine for orienting objects who should perform smooth rotations.
It is the camera system's job to smoothly interpolate from its current orientation to the newly computed orientation. This is where quaternions begin to work their magic and are worth their weight in gold.

gluLookAt simplifies the following process which is another way to orient an object to face another object:

• Create a vector from the source object to the target object and normalize it
• Perform a dot product between the look vector of the source object and the vector to the target. This is the angle of rotation needed.
• Perform a cross product between the look vector of the source object and the vector to the target and normalize the result. This is the axis of rotation.
• Rotate the source object by the arccos of the angle found in the second step about the axis found in the third step.

14. That question as a specific purposs and it was not meant for you.

15. Um who are you talking to? This is a public forum so anyone can chime in when they so desire.

Popular pages Recent additions