Fov calculation

Hi,

I’m trying to compute the right fov for a scene. For testing purposes, I’ve created a cube starting at (0,0,0) and ending at (100,100,100). Then, inspired by the ‘red book’, I’ve done this :


glMatrixMode(GL_PROJECTION);
glLoadIdentity();
/* Cube has size 100 and its distance to the
camera is 200 since the camera lies at (300,50,50) /
fov = calculate_angle(100.0,200.0);
gluPerspective(fov, (GLfloat)width/(GLfloat)height, 10.0, 500.0);
glMatrixMode(GL_MODELVIEW);
/
Viewport : right view /
glViewport (0, 0, (GLsizei)width, (GLsizei)height);
/
Set camera position (viewing transformation) /
glLoadIdentity();
gluLookAt(300.0, 50.0, 50.0, 50.0, 50.0, 50.0, 0.0, 1.0, 0.0);
/
Draw Cube (not centered at the origin) */
draw_cube();
[…]

where calculate_angle is :

/* Calculates the projection’s fov. It requires
the size of the object and its distance from the
viewpoint */
double calculate_angle(double size, double distance)
{
double radtheta, degtheta;

radtheta = 2.0 * atan2(size*0.5,distance);
degtheta = (180.0 * radtheta) / PI;
return degtheta;

}


The problem with this approach is that the produced fov is too small and the cube doesn’t fit entirely on screen. For instance, using the values in this example the produced fov is 28.072 when a fov of at least 60.0 is needed. I’m completely at a loss here, so any help would be greatly appreciated. Thanks.

Frederico Jeronimo

seems like your angle is half what it should be… you’re sure that “size” is correct? (ie, that the cube doesn’t extend from size to -size?)

also – and this is kinda nit-picky – let your compiler do most of the work when converting from radians to degrees:

d = r * (180.0f / PI);

Originally posted by phlake:
seems like your angle is half what it should be… you’re sure that “size” is correct? (ie, that the cube doesn’t extend from size to -size?)

Hmm… I think the size is correct. I’m using these coordinates :
static GLint vertices = { 0, 0 ,0,
100, 0, 0,
100,100, 0,
0,100,0,
0,0,100,
100,0,100,
100,100,100,
0,100,100 };
This gives a 100-sized cube (since size in this case is the difference between the top and bottom of the object), right?

Frederico Jeronimo

That cube is 100 units large, yes. It extends from 0 to size (where size = 100), but calculate_angle assumes the box is extending from -size to size. Or at least this is the angle you get, which you then pass directly to gluPerspective.

In short, your calculations assumes the cube’s center is located at the local origin, while your testcube’s center is located at (50, 50, 50).

Originally posted by Bob:
[b]That cube is 100 units large, yes. It extends from 0 to size (where size = 100), but calculate_angle assumes the box is extending from -size to size. Or at least this is the angle you get, which you then pass directly to gluPerspective.

In short, your calculations assumes the cube’s center is located at the local origin, while your testcube’s center is located at (50, 50, 50).[/b]

I’m still confused. Why does calculate_angle assume that the cube is between (-size, size)?

Quoting from the ‘red book’ : “You can use trigonometry to calculate the desired field of view given the size of the object and its distance from the viewpoint : the tangent of half the desired angle is half the size of the object divided by the distance to the object”

So, why do I need to pass the double of the object’s size (200) for it to work?

Thanks for any further help

Frederico Jeronimo

Anyone has any extra clues? Thanks in advance.

Frederico Jeronimo

radtheta = 2.0 * atan2(size*0.5,distance);

I think this line is not what it supposed to be. Try remove *0.5. This is the line that assumes the cube center is located at it’s own local origin, which it isn’t in your code. If you pass a size of 100, then it will assume the cube is extending from (-size/2) to (size/2), and not from 0 to size.

I’d say that you need to subtract the half size of the cube (‘radius’) from the distance to the cube, because you need to be able to see the whole near face. You should obviously use the diagonal of the cube if you intend to orient it.

Originally posted by Bob:
[b]radtheta = 2.0 * atan2(size*0.5,distance);

I think this line is not what it supposed to be. Try remove *0.5. This is the line that assumes the cube center is located at it’s own local origin, which it isn’t in your code. If you pass a size of 100, then it will assume the cube is extending from (-size/2) to (size/2), and not from 0 to size.[/b]

Hmm… I tried centering the cube at the origin to no avail. It leads to the same result. I don’t think that the cube’s position really matters as long as the camera is looking right at its center (which it is). Also, the code found in the ‘red book’ makes sense mathematically speaking (or at least I think it does).

Consider the following sketch :

d : distance from camera to object
h : cube’s height
f : fov

  (sorry for the uglyness)


.^…x…
…|…x…
…|…x.f/2
h|…x…o(camera)
…|…x.f/2/
…|…x…/
…v…x…/
…/
…<----->
…d

Looking at the above picture, we have that :

tan(f/2) = (h/2) / d

therefore,

f/2 = arctan ( (h/2) / d);

which is the formula I used…

This one is really puzzling me.

Thanks for all those trying to help me out with this.

Frederico Jeronimo

[This message has been edited by Jeronimo (edited 11-13-2001).]

[This message has been edited by Jeronimo (edited 11-13-2001).]

[This message has been edited by Jeronimo (edited 11-13-2001).]