Navigation

I am attempting to provide a simple navigation for users walking thru 3d worlds. It is set up so that the arrow keys move the user forward, backward, strafe left, and strafe right and that the mouse is what turns the user. If the user moves the mouse to the left hand of the screen, then one turns right, to the right hand side and one turns to the right.

Now, here for my problem. If i use:

gluLookAt(headx, heady, headz,
lookatx, lookaty, lookatz,
0, 1.0, 0);

// does the left/right viewing
glTranslatef(headx, 0.0, headz);
glRotatef(rotateWorldy, 0, 1, 0);
glTranslatef(-headx, 0.0, -headz);

where headx,heady,headz are the current position of the user, and lookatx,y,z is some arbitary point further down the z axis.

Using the above code, the user turns like he is supposed to, but the forward, back, strafe left/right stay the same in relation to the original view. Ie. If the person turns 180 degrees then the forward and back keys are inverted.

if I use the following code:

// does the left/right viewing
glTranslatef(-headx, 0.0, -headz);
glRotatef(rotateWorldy, 0, 1, 0);
glTranslatef(headx, 0.0, headz);

then the forward/back/left/right keys adjust depending on the view and forward will always be forward. However, by doing this, when I rotate the world, it does not rotate about me, but rather about some other point.

So, how would I go about implementing this navigation structure where 1) the forward/back/left/right keys are always relative to the current view and not the origianal world parameters and 2) that when the user looks left/right that the world rotates about the camera and not about some arbitrary point.

It is a bad idea to use gluLookAt to change your camera position as well as change it by glTranslate and glRotate. And, it makes no sense to have multiple glTranslate calls to change your camera position. They both change the current matrix and would be equivalent. The only reason you needed the first call to glTranslate was that you were correcting for the translation resulting from the gluLookAt command.

Just use glRotate and then glTranslate, and you should get the expected results unless other parts of your code are also questionable. Or, just use gluLookAt. Not both!

For constant camera orientation default gluLookAt(0.0, 0.0, 0.0, 0.0, -100.0, 0.0, 0.0, 1.0, 0.0);//implies always looking down the -z’

glRotatef(rotateWorldy, 0, 1, 0);
glTranslatef(headx, 0.0, headz);

or

dynamic camera position

gluLookAt(headx, heady, headz, lookatx, lookaty, lookatz, 0, 1.0, 0);

I think most people prefer to translate and rotate rather than deal with camera position directly, but choice is yours. Don’t use both… counterproductive, unless you are going to implement mouselook feature from Unreal Tournament, etc where your body is oriented in one direction but you can look in another and strafe and shoot but your body is moving in direction other than your facing. Even then it would be easier to use glRotate.

[This message has been edited by shinpaughp (edited 03-25-2003).]

When I tried your suggestion:

gluLookAt(0.0, 2.5, 0.0,
0.0, 2.5, -100.0,
0.0, 1.0, 0.0);

// does the left/right viewing
glRotatef(rotateWorldy, 0, 1, 0);
glTranslatef(-headx, 0.0, -headz);

the problem I now face is that if i rotate 180 degrees, my keys are the wrong we around… ie. forward is backwards and backwards is forwards…

is there a quick fix for that?

Are your headx and headz dependent on your angle. They should be.

example:

headz += deltamove * cos(rotateWorldy);
headx += deltamove * sin(rotateWorldy);

for moving forward at least. And, I think your translate should be positive, not negative, but you may have that for a reason. Or you are doing this within projection matrix rather than modelview matrix as is recommended.

edit:
you’ll have to check the signs. I think z should be -=.

edit2:
And if your code is already set up for using gluLookAt to change your camera position, you might do that and not use the rotate and translate. Whichever is easier for you to do rather than having to go through and entirely change your code.

[This message has been edited by shinpaughp (edited 03-25-2003).]

Hi,

I’ve always found vectors easier to deal with than trigonometry. So you have eye, target and up vectors which you use with gluLookAt.

When the mouse moves, rotate the target around the eye position.

When the eye must be moved forward/backward, move it along the direction of the eye->target vector. When it’s moved sideways (strafing) get the right vector by taking a cross product between the eye->camera vector and the up vector, and move along this vector.

-Ilkka

Just wanted to say thanx - it works wonderfully now with cleaner and simpler code.