gluPerspective and glFrustum (come, it's east...right?)

It’s a pretty simple question really:

When I use glFrustum is doesn’t work. When I use gluPerspective, it does. Why?

What is it that gluPerspective actually does to set the left, right, top and bottom clipping planes…

We know very very trivally, that the near distance defines the projection plane, so basically your FOV is:

FOV1 = 2 * atan(((top-bottom)/(near2.0))
FOV2 = 2 * atan(((right-left)/(near
2.0))

Or rather, in the reverse:

top-bottom = tan(FOV1/2) * (near2.0)
left-right = tan(FOV2/2) * (near
2.0)

However, using these forumla to generate the
left/right/top/bottom values from a near (far
is irrelevant) generates a perspective
transformation that has very small clipping
planes, and doesn’t seem to work at all.

Using gluPerspective to generate these
somehow make everything OK; and I don’t know
why.

In fact, nobody I’ve talked to so far really
seems to understand glFrustum at all; they
know the basics (above) but use
gluPerspective “because it works”.

Any ideas people? It can’t be that
complicated, can it? I know gluPerspective
generates the matrix to use directly… I’m
looking for justification for why it
generates that matrix.

cheers,
Doug.

… and just absently, I did hunt through the archives, but what I found contradicted itself and was other wise just plain wrong.

From b4, if you allow; bottom = -top, then:

2 * top = tan(FOV1/2) * (near*2.0)
top = tan(FOV1/2) * near

This (which is more less what I expect) snippet:

"void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar )
{
GLdouble xmin, xmax, ymin, ymax;

ymax = zNear * tan( fovy * M_PI / 360.0 );
ymin = -ymax;

xmin = ymin * aspect;
xmax = ymax * aspect;

glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
}"

Does that, but I’m still dubious. What’s with the xmin = ymin * aspect?

If your fov is a ratio then would you not:

right = tan((FOV2 * aspect)/2) * near

Otherwise your FOV2 angle is lost; and regardless, K*(tan(FOV1/2) * near) != (tan(FOV1*K/2) * near).

Hmm… so yes. That didn’t help at all.

Originally posted by Shadow Mint:
…What’s with the xmin = ymin * aspect?

If you look at the FOV1 and FOV2 equations in your first post, you’ll see that these angles are related to each other. One is in the y direction and one in the x. If we know one of them then we can find the other if we know the aspect ratio (the ratio of x/y). This means that a second (expensive) trig function is not needed. That’s why FOV2 is irrelevant.

Does that make any sense??

[EDITED] Just a thought, but you are expressing the angles in radians in your “manual” frustum calculation aren’t you? gluPerspective() uses degrees but tan/atan etc. use radians…

Yes, I see from your second post that you are! Just ignore me - I’ll go away now …[/EDITED]

[This message has been edited by Rog (edited 05-21-2003).]

[This message has been edited by Rog (edited 05-21-2003).]

If you look at the FOV1 and FOV2 equations in your first post, you’ll see that these angles are related to each other.

Ah!! With out actually saying it you’ve hit right on the mark.

So basically, the objective is to eliminate the distortion associated with an non-symetric (DX!=DY) window.

Distortion occurs when a square projection plane (FOV1=FOV2 say) is rasterized onto a non-squard viewing window.

If you consider a symetric window that is then changed by Dx->Dx*2, look at the projection plane vs. the viewing window. To avoid distortion the ratio of the sides of the projection plane to the viewing window must be the same.

Thus, (Dx/Dy)=((right-left)/(top-bottom)) or the output will be distorted.

So, you can effectively just increase the size of the projection plane (left = left * aspect, right = right * aspect) OR manually calculate an entirely new projection plane from two FOV values, as long as you maintain the aspect ratio.

If this case what I proposed before; FOV2 -> FOV2 * aspect will not work, because the solution to:

left-right / top-bottom != aspect

(To solve this correct recall:

top-bottom = tan(FOV1/2) * (near2.0)
left-right = tan(FOV2/2) * (near
2.0)

Thus:

left-right / top-bottom = tan(FOV2/2) * (near2.0) / tan(FOV1/2) * (near2.0)
left-right / top-bottom = tan(FOV2/2) / tan(FOV1/2)

ie. Aspect = tan(FOV2/2) / tan(FOV1/2)

Which is non-trivial to solve I guess.)

So yeah,
Thanks.