Jump to content
  • Advertisement
Sign in to follow this  
mbanghart

Moving camera in 3D

This topic is 3717 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I am building a flight simulator. When the user presses the left key the camera shoudl rotate left. I don't have a problem to get that to work. When they press UP they should continiously move forward, until back is pressed. I know how to move the camera continiously along an axis. My problem is how do I continiously move forward in the rotated direction? For example: If they havent pressed left (and not rotated at all), I move forward by calling glTranslate(0,1,0);. But after I rotate with glRotate(4,x,y,z) and then call glTranslate(0,1,0) I basically "strafe". I want to move in the direction that the camera is pointing. I am assuming this is a linear algebra problem (which I haven't taken). Thanks

Share this post


Link to post
Share on other sites
Advertisement
I think I found a partial solution. This solution rotates around the Y axis. How can I change it to rotate around the Z axis?

Link: http://www.lighthouse3d.com/opengl/glut/index.php?6

Share this post


Link to post
Share on other sites
In your simulator, you'll be expecting full 6DOF, so start-off with quaternions and avoid gluLookAt. The jet can be flying (pointing) directly upwards, after all.

Some pseudo-code:


Vec3 jet_position = Vec3(0,0,0); // calculated in the code below
Quat jet_orientation; //modified by other code

float speed=0; // modified by other code

void Render(){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslate(-jet_position);

Mat3x3 rotation = jet_orientation.ToMatrix();
Mat4x4 rotation4x4 = Mat4x4_identity;
rotation4x4.setRotation(rotation); // this simply copies a 3x3 matrix to 4x4

glMultMatrix(rotation4x4);

.. now render
}
void UpdateJetPosition(){
Mat3x3 rotation = jet_orientation.ToMatrix();
Vec3 speed3 = Vec3(0,0,speed); // as if the aircraft flies only forward to Z
Vec3 speed3_rotated = rotation * speed3; // this rotated the above direction

jet_position += speed3_rotated;
}


I could have mistaken some +/- sign somewhere, as I'm still inexperienced to 3D maths.

Share this post


Link to post
Share on other sites
Hi mbanghart,

hi think the problem you are experiencing is caused by the order of the transformations. When you are not sure about the order of a translation and a rotation, try to exchange them; a lot of times the difference in the result will give you an idea of what's going on.

Second, you may find useful the function gluLookAt():

http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/glu/lookat.html

That basically can do the job for you. The problem of simulation and rendering can be split in two parts. For instance, if your camera is in the point (x, 0.0f, z) and is looking to the point (cx, 0.0f, cz), you can call gluLookAt() in the following way:

gluLookAt(x, 0.0f, z, cx, 0.0f, cz, 0.0f, 1.0f, 0.0f);

Assuming hence no roll:

http://en.wikipedia.org/wiki/Flight_dynamics

Having an algebraic background helps, however what really is fundamental is the concept of transformation, and it's pretty supported by the OpenGL matrix functions. Once you fix a homogeneous reference system, spatial transformations (translation, scale and rotation) and 4x4 matrices are equivalent. Scale and rotation can be done with 3x3 matrixes in a conventional reference system, but not the translation; hence the need of using 4x4 matrixes and homogeneous reference. But as I told you, you don't really need this.

OpenGL stores the current transformation in an inner state variable; all the matrix functions operate on that transformation, and save the result in the same variable. There are three of this transformations, used in different stage of the rendering: the current one can be set calling the function glMatrixMode().

http://www.opengl.org/sdk/docs/man/xhtml/glMatrixMode.xml

Transformations operate on points; when you call glVertex3f(x, y, z), the vertex v=[x, y, z] is first transformed using the GL_WORLDVIEW transformation, and then sent to the screen in a position obtained transforming again with the transformation GL_PROJECTION. When a vertex v is transformed by a transformation A you can express the result as:

A(v)

Which means, A applied to v. Probably you need to set GL_PROJECTION just once, at the beginning of the program. Moving the camera is a matter of setting GL_WORLDVIEW.

The composition of two transformations A and B can be expressed with:

A(B(v))

In which v is transformed with B, and then the result is transformed again with A.

The function glIdentity() puts an identical transformation in the current transformation; the identical transformation doesn't do anything. You should call glIdentity() in order to initialize the variable on which you will work.

All the subsequent calls to matrix functions combine the current transformation with the transformation specified by the particular function you call. MORE RECENT CALLS ARE APPLIED FIRST! This means that the following code:

glMatrixMode(GL_WORLDVIEW);
glIdentity();
glTranslatef(0.0f, 0.0f, -1.0f);
glRotatef(45.0f, 0.0f, 1.0f, 0.0f);

Will FIRST perform a rotation R and THEN a translation T; it corresponds to:

T(R(v))

While the following code:

glMatrixMode(GL_WORLDVIEW);
glIdentity();
glRotatef(45.0f, 0.0f, 1.0f, 0.0f);
glTranslatef(0.0f, 0.0f, -1.0f);

Will FIRST perform a translation T and THEN a rotation R; it corresponds to:

R(T(v))

The visual difference between this two snippets is that in the first one you first rotate the camera and then you step forward, while in the second is the opposite.

Hope I helped you a little bit! Bye!

Share this post


Link to post
Share on other sites
damix911, airplanes can fly upside-down for a while - so the "up" vector in gluLookAt will ruin things. Also, if you make the camera look at a place right above it, rotation around the "up" vector cannot be known. I think I've seen that cause random rotations thanks to tiny precision errors getting multiplied by large numbers while being normalized. Thus, I think gluLookAt is useless in flight-simulators.

Share this post


Link to post
Share on other sites
Hi idinev, yes actually I was only thinking to a very simple solution to turn left and right (no pitch and roll), for this reason I have choosen the vector [0, 1, 0]. You are right when you say there is a problem with gluLookAt() and up vector for flight simulators; I wrote two simple (ugly) flight simulators in DirectX, and I remember I had a hard time to make them work properly; but I used the equivalent function D3DXMatrixLookAtLH() exactly because it was quite comfortable for the six degrees of freedom. The state of the plane was described by a position P, a direction D and a up vector U. I actually had to update the up vector U in order to be orthogonal with the direction, and this is actually the annoying part. But after this, you have a local reference system in wich D is a z-axis (negative z in OpenGL), U is a y-axis, and a x-axis can be obtained by doing the cross product D x U. At that point you can map those axis to buttons on they joypad and you have three of the six degrees almost for free. And this vectors are also good for the function D3DXMatrixLookAtLH/gluLookAt because the first three arguments are in P, the second three arguments are in P + D, and the last three arguments are in U.

Share this post


Link to post
Share on other sites
Thanks for the help. Right now I am not trying to create a 6DOF simulator. Just a basic one that ignores pitch and roll. I ended up having it work without using glLookAt. Just glRotate and glTranslate. Still having some rotation problems since I don't my position at any given point (so I have rotate around the origin).

Will probably have to add some variable to keep track of all translations.

Share this post


Link to post
Share on other sites
Hi mbanghart, you can try with something like this.

Your state in the game can be represented by position on a 2D map, something like:

float x, z; // position

and an angle, representing the direction of looking:

float alpha; // direction of looking

The two problems of updating the state and rendering the scene can be solved separately.

=== Updating the state ===

Let's suppose that the time elapsed from your last updating is t. The new position is hence:

x = x + (t * speed) * cos(alpha);
z = z + (t * speed) * sin(alpha);

If you don't want to take in account time, and you simply want to step forward or backward when buttons are pressed, you can substitute the term (t * speed) with whatever you like, for instance 0.1f, 1.2f, aValueOfYourChoice.

In addition, then the user presses the right button, your program should do:

alpha -= 1.0f;

instead, when the user presses the left button, your program should do:

alpha += 1.0f;

=== Rendering the scene ===

You have to translate the plane position in the origin, and then you must rotate the world to simulate the rotation of the camera; remember that the LATEST you call a transformation, the EARLIEST it is applied.

glMatrixMode(GL_MODELVIEW);
glIdentity();
glRotatef(-angle, 0.0f, 1.0f, 0.0f);
glTranslatef(-x, 0.0f, -z);

The minus is used because you are actually moving the world, not the camera; so directions and angles must be inverted.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!