Skip to main content
gamedev.net
🔒 Locked

I get around... 2D rotation problem

Started by webwraith 6 replies 1.7k views
Original Post
webwraith
webwraith
I am having troubles with moving my camera. I have a position vector(x,y,z), a pitch value, a yaw value and a local move vector(_x,_y,_z) I understand that to get the cameras new position, I need to translate back to the origin, rotate the local vector,then translate back to the start, and add the local move vector to the position vector. The current code I have for this is;

glRotatef(yaw,0.0f,1.0f,0.0f);
glRotatef(pitch,1.0f,0.0f,0.0f);

x += _x*COS(yaw) - _z*SIN(yaw);
z += _x*SIN(yaw) + _z*COS(yaw);

glTranslatef(x*0.001f,y*0.001f,-5.0f+z*0.001f);

where COS() and SIN() are inline functions that convert cmath's cos() and sin() functions to degrees. However, when my program runs, although camera tilt and pan from the mouse works perfectly, the movement fails. Could someone correct me, and provide an explanation? Many thanks
Zakwayda
Zakwayda
Quote:
I understand that to get the cameras new position, I need to translate back to the origin, rotate the local vector,then translate back to the start, and add the local move vector to the position vector.
This is not how it's typically done.

Although you might be able to hack this together with trigonometric operations and OpenGL function calls (as you're trying to do currently), in the long run you'd be better off maintaining the camera transform yourself (e.g. in matrix form).

The first thing to do is to forget (for the time being at least) that you're dealing with a camera, and just ask yourself, how would I go about moving a 'regular' object about?

In your case, you have three parameters to worry about: yaw, pitch, and forward/backward speed (we can set aside strafing for now, as it's very similar to forward and backward movement). The object's transform can be stored in any number of ways, but for this example we'll use a 3x3 matrix (the orientation) and a vector (the position). A typical update for your object will proceed as follows:

1. Build the rotation matrix from the object's yaw and pitch.

2. Derive a forward vector from the yaw and pitch. If you want motion to always be parallel to the ground plane, this can be done with a little trig. If you want motion to be in the direction that the object is 'looking', you can extract the direction vector directly from the matrix.

3. Update the position using the direction vector and the current speed of the object.

4. Build a final 4x4 transform matrix from the 3x3 orientation matrix and the position vector.

To use the object as a camera, only one more step is required, and that is to invert the matrix. You can then submit it directly to OpenGL via glLoadMatrix().

Obviously there are a few details involved, but that's the basic idea.
webwraith
webwraith
Do I need to worry about the cameras pitch, if I am translating across the ground? I thought it would be simply 2D rotation rather than 3D, although I see what you mean about treating it like every other in-game object. Do you think I should bother adding roll to this, or is it too much to worry about in the beginning?
Zakwayda
Zakwayda
Quote:
Do I need to worry about the cameras pitch, if I am translating across the ground?
If you want linear motion to be parallel to the ground plane, then you don't need to factor in pitch when calculating the movement vector.
Quote:
Do you think I should bother adding roll to this, or is it too much to worry about in the beginning?
That's up to you :) However, incorporating roll will add some complexity, so if I were you I'd leave it out until you have an otherwise working implementation.
webwraith
webwraith
What is the simplest way to invert a matrix in code?I've found plenty of tutorials on matrix inversion, but they are all pretty complex, and designed for someone doing the inversion on paper. Should I keep a separate matrix and apply the inverse of each transform to that instead?

[Edited by - webwraith on October 1, 2008 10:04:31 AM]
webwraith
webwraith
Right, I'm not using the marix form just yet, as I can't get this to work without it. I've taken the trig functions directly from the rotation matrix, so it should do the exact same thing.

These are the position manipulation functions;
void ResetVector(vector& v) /* sets a vector to [ 0 0 ] */{        v.x = v.y = 0;}void RotateVector(vector& v, float angle){        v.x = v.x*COS(angle)+v.y*SIN(angle);        v.y = -v.x*SIN(angle)+v.y*COS(angle);}void NormalizeVector(vector& v){        float w = sqrt(v.x*v.x + v.y*v.y);        v.x /= w;        v.y /= w;}void MultVectorScalar(vector& v, float f){        v.x *= f;        v.y *= f;}


where vector is;
struct vector{        float x,y;};


When I do the following;
/* Rotate the camera */vector target;NormalizeVector(target);target.x = rt;  /* rt and fwd are set to either 1.0f or -1.0f, depending */target.y = fwd; /* on which direction key is pressed, or 0.0f if no key  */RotateVector(target,yaw);MultVectorScalar(target,spd);position.x += target.x;position.y += target.y;glTranslatef(position.x,0.0f,(-5.0f+position.y));

The view flies about wildly, and seemingly at random when I press one of the direction keys.

I've been using the 2D rotation and translation information I could find, but I still can't get it to behave. I'm pulling my hair out over this one
Zakwayda
Zakwayda
I see an obvious mistake in the following function:
void RotateVector(vector& v, float angle){        v.x = v.x*COS(angle)+v.y*SIN(angle);        v.y = -v.x*SIN(angle)+v.y*COS(angle);}
You overwrite the value of v.x, and then use the new value in the next line of code (where it should be the original value). To fix this, use a local temporary for one or both vector elements.
webwraith
webwraith
Thanks, jyk, that has helped with preventing my test object (a red triangle) from just disappearing, but I'm still having trouble with my movement. Forward and backward keep seeming to swap at random, while left and right seem to suddenly decide to become forward and backward. Also at random.

My movement method involves setting fwd and rt to 1.0f or -1.0f, depending on the keys pressed, then plugging these values in to the target vector before calling the RotateVector() function. I assumed this was correct, as it would be taking the direction to move, and rotating it, before adding the result to the current position. Is there something else I'm missing?

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.