PDA

View Full Version : using camera's in opengl


Lau83
07-11-2005, 11:27 PM
Hi,

I'm programming my own OpenGL 3d engine and its coming along nicely. After completing the polygon/model, lighting and texture manager for the engine, I decided it was time to include a way to create virtual camera's.

I did some research and saw many examples. Some mentioned using the glTranslatef function (which I'm already using btw for drawing objects in the scene) in combination with rotatating the scene. Other examples said I should use matrix functions (btw...I'm really bad in matrix calculations, so if anyone could find some nice tutorials for this, it would be greatly apriciated)

My question is... which of the two should I use? Or should I use another entirely different technique?

BTW: I'm NOT using glut or anything just the standard OpenGL API

ace4016
07-12-2005, 02:37 AM
Have you ever tried nehe.gamedev.net ( http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=Quaternion_Camera_Class )? I haven't tried it but once yo mentioned cameras, that tutorial was the first thing that came to mind. Hope it helps.

playmesumch00ns
07-12-2005, 08:39 AM
That tutorial's probably slightly more opaque that it could be because it deals with quaternions.

To understand what's going on in opengl you should have a basic understanding of matrix transformations. Any introductory book on "maths for computer graphics" or something similar will help you here.

What you basically need to know is that matrices can be used to represent 3d transformations. A matrix might represent a translation, or a rotation etc. By combining matrices together, called concatenation, you can represent a number of successive transformations with a single matrix. So if T were a translation matrix and R were a rotate matrix, the single matrix

M = TR

would be the end result of a rotation followed by a translation.

Internally, OpenGL keeps track of a matrix, called the Model-View matrix. This matrix defines the mapping from object space (where you specify objects' verices) to view (camera) space.

We normally think of objects being defined in world space, i.e. each object is defined relative to its own coordinate system, then we apply transformations (the modelling transformation) to that object to place it in the world. OpenGL makes no distinction between world and view space (though directx does). You can think of this as having a fixed camera always placed at the origin, looking down the -Z axis.

So if there's no distinction between world and camera space, how do we put the camera "somewhere in the world" and have the image change accordingly?

As you've already said, the answer is to transform the whole scene by the inverse of the camera transformation. If you think about it, there's absolutely no difference between, for example, moving the camera ten units closer to your object, or moving your object ten units closer to your camera.

So to achieve this, you draw loop should look something like

<choose camera>

void render()
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

<applyInverseCameraTransformation>

glBegin();

for each ( object in scene ) {
glPushMatrix();

<apply object's modelling transformation>
<draw object>

glPopMatrix();
}

glEnd();
}


The best way to store you camera class is usually as seperate translation and rotation components, as then it's easier to intepolate. You can then build and invert the camera matrix yourself before loading it into gl with glLoadMatrix().

An easier way is just to use gl functions to do it for you. so

class Camera
{
public:
virtual void applyInverseTransform();
}

/// class OrbitCamera. applies a simple orbiting camera for viewing objects
class OrbitCamera : public Camera
{
public:
void applyTransform() {
glRotatef( -ry, 0, 1, 0 );
glRotatef( -rx, 1, 0, 0 );
glRotatef( -rz, 0, 0, 1 );
glTranslatef( -tx, -ty, -tz );
}

private:
float tx, ty, tx;
float rx, ry, rz;
}


/// class LookAtCamera
class LookAtCamera : public Camera
{
public:
void applyTransform() {
gluLookAt( ex,ey,ez, cx,cy,cz, ux,uy,z );
}


private:
float ex, ey, ez;
float cx, cy, cz;
float ux, uy, uz;
}



given the above,


<choose camera> =
Camera* cam = new LookAtCamera();

and

<apply inverse camera transform> =
cam->applyTransform();

Lau83
07-12-2005, 10:17 AM
Wow!

Many thanks to both of you! I will seriously take a look into this.

playmesumch00ns: Thanks for the detailed information! You certainly pushed me back in the right direction again and it's already making more sense to me now :thumbsup:

Oh and I do have a book on computer graphics (Computer Graphics: Practices and Principles - Second Edition in C), but it's more focussed on Lineair Algebra as a whole, so it was a bit overwelming for me, but I'm still studying it, one step at a time, to try to fully understand it!

arnecls
07-12-2005, 11:08 AM
A good book to understand the basics is IMHO Fundamentals of Computer Graphics by Peter Shirley. Realtively easy to read and contains lot's of interesting things for beginners (though not directly OpenGL realted).

I've already written some camera classes ^^ and ended up with the following solution:
If you're programming with c++ you probably already have a class for 3D-vectors and/or quaternions and/or 4by4 matrixes.
If not - I would strongly suggest to implement them, as you always have to do some vector calculations on the cpu and this way your code becomes more readable (because operator overloads are sooo nice here :).
Do this once and you'll never want to live without those ;)

My camera class takes two vectors, eye and lookat. Eye ist the position of the camera, lookat the viewing direction of the camera. Some tend to use a lookat position here, but I found it easier to rotate my camera with a unified direction instead of a position. Up is always 0 1 0 for me. This works perfect with gluLookAt and I can easily rotate my camera by supplying a quaternion or Matrix to a transform function. Due to my math classes (as described above) those are mostly 3-line functions ^^.

Lau83
07-12-2005, 11:49 AM
arnecls: I'm indeed using C++, using classes and all that stuff. But I'm realizing now, that programming a decent engine is more work then I originaly anticipated. (And I really have to learn how matrixes work).
But I'm gonna finish this, cause I'm also having lots of fun learning and making all of this :bounce:

CGTalk Moderation
07-12-2005, 11:49 AM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.