Troubles figuring out how perspective projections work

I’ve been tinkering around with OpenGL in my spare time trying to figure it out, and I’m doing pretty well in understanding most of it, but for some reason or another perspective projections and viewing volumes and the like just aren’t clicking for me…

I think what I’m having troubles with is mainly the relationship between camera positioning (using gluLookAt) and how functions like gluPerspective() actually create a viewing volume…

Any pointers would be very helpful… thanks!

(P.S. I’m having very bizarre troubles with VC++ 6, for some reason or another, when I write two for-loops to iterate through a 2 dimensional array, only the inside loop iterates itself, the outside loop stays at 0, or at least that’s what the debugger would have me think, as far as i can tell there’s no coding errors, two for-loops should be simple enough,
for(int i = 0; i < 256; i++) {
for(int j = 0; j < 256; j++) {
bits[i][j] = ???;
}
}
thanks again for any insight)

—plucky

Just to make it clear from the beginning, there is no camera in OpenGL, just a viewpoint located at the world origin (0,0,0), looking down the positive z-axis.

Anyways, gluLookAt translate the entire world, so that it appears that you are located at the specified point, looking at whatever point you said. Moving your “camera” one unit forwards, is the same as moving the world one unit backwards. Same with rotation, rotating the “camera” one degree to the left, is the same as rotating the world one degree to the right.

gluPerspective creates a pyramidical viewing volume, based on the values you pass. Since it knows the field of view, the aspect ratio, and the near and far plane, it can calculate all corners in the viewing volume, and then pass them to glFrustum(). The projection matrix simply transforms all visible point to the screen, scaling the size so that objects far away is drawn smaller.

A viewing volume is like a box. All points inside this box is projected onto one of the sides of this box, the screen. All points outside, is either clipped to fit inside the box if is’t a part of a partly visible polygon, or simply rejected if not visible at all.

And yeah, did you put a semicolon after one of the for loops, or maybe messed up the variables?

for(i=0; i<256; i++)
{
for(j=0; i<256; i++)
{
// yada yada
}
}

When the inner loop reaches 256, then outer loop is completed too.

Thanks for replying!

however, i don’t think that i stated my problem quite right…

my confusion is more in how gluPerspective() actually creates a volume, given a set of arguments…

for example, if i were to say gluPerspective(90.0, 800.0 / 600.0, 1.0, 100.0); what kind of volume could i expect?

when i see a function call like this, i’m not exactly sure what the volume is going to look like… where the near and far planes are located on the z-axis, what the min and max x and y are for the near plane (and ditto for the far plane), etc…

is there some way that i can get the frustum drawn on the screen and then move the viewpoint out above it, so that i can look at what the frustum would look like if the viewpoint was at the origin? (sorry if that was confusing)

thanks again

(ps. the whole for-loop thing looks like it is written correctly, i’m almost 100% sure of it… which is why i can’t figure out what the hell is causing the outer loop not to increment at all…

see what happens is, when my program hits those loops during execution, it just keeps counting the inner loop from 0 to 255 while the outer loop stays at 0… so the outer loop never breaks, and the program just sits there, counting from 0 to 255 over and over…)

Hmmmm… strange. Sounds like a bug

Have you tried this:

int i,j;
for(i = 0; i < 256; i++) {
for(j = 0; j < 256; j++) {
bits[i][j] = ???;
}
}

instaed of:

for(int i = 0; i < 256; i++) {
for(int j = 0; j < 256; j++) {
bits[i][j] = ???;
}
}

???
(I don’t ever had such a problem, so I’m just speculating)
(And you don’t have anything like i=… in the inner loop?)

gluPerspective(90.0, 800.0 / 600.0, 1.0, 100.0) will create a viewingvolume, with the near plane located at Z=1, and the far plane located at Z=100. These two values are kinda easy to get

Now, there are four pointe left to calculate, and we call then r (right), l (left), t (top) and b (bottom). The point (l, b) is the point on the near plane that will be projected onto the left bottom pixel in the viewport. Same with (r,t), but will be projected on the top right pixel.

t = near * tan(fov)
b = -1 * near * tan(fov)
l = near * aspect * tan(fov)
r = -1 * near * aspect * tan(fov)

So, with the following variables, the points in the corner of the near plane would be (l,t), (r,t), (r,b) and (l,b).

If you replace near in the formulas above with far, you get the point on the far plane instead.

And you can calculate all eight corners, and draw them as a cube. Before drawing the cube, you just change the viewpoint. Then you are looking at your frustum from the outside.

However, doing so will probably clip the lines of the cube, since moving a little bit in one direction will cause one or more vertices to fall outside the frustum.

Thanks for your help Bob, I really appreciate it… I think I finally get it now!

Regarding the strange for-loop stuff, my problem with that seems to have fixed itself now that I’ve gone back to Win2K insteak of WinMe (which caused me a ridiculous amount of pain)

Thanks again!!