glFrustum, gluPerspective and FOV

4.5k views Asked by At

I have a program to do augmented reality and in OpenGL I use :

glFrustum(-near*centerImageX/(GLfloat)fx, near*(imageWidth-centerImageX)/(GLfloat)fx, near*(centerImageY-imageHeight)/(GLfloat)fy, near*centerImageY/(GLfloat)fy, near, far);

This is ok, I get the good perspective and my 3D object is well inserted on my photo. Now I would like to be able to zoom in/out. Normally, it's done by changing fov in gluPerspective but I don't use gluPerspective because I can't get a good insertion.

With http://dmi.uib.es/~josemaria/files/OpenGLFAQ/transformations.htm, question "9.085 How can I make a call to glFrustum() that matches my call to gluPerspective()?", I tried with :

fov=360.0*atan(imageHeight/(2*fy))/Pi;  //computed with parameters top and bottom of my glFrustum
aspect=-centerImageY*fx/(fy*(centerImageX-imageWidth)); //computed with parameters left and bottom of my glFrustum

void glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);

void gluPerspective( GLdouble fovy, GLdouble aspect,GLdouble near, GLdouble far );

And then :

gluPerspective(fov, aspect, near, far);

But my object is distorted, it's not scaled correctly on all axes, ratio is not kept.

So what do I need to do / modify in my glFrustum parameters to get a zoom in / out effect ?

2

There are 2 answers

3
vallentin On

Normally, it's not done by changing the fov in gluPerspective().

Normally, you would apply transformations to the model and/or view matrix for that matter. If you want to move the model, you usually do that in the Model Matrix. If you want to change "the camera position", you usually do that in the View Matrix.

In your case, you would probably translate the View Matrix. As that would resolve in the illusion of your 3D object moving away or coming up closer to the camera.

If you're still using the fixed-function pipeline, you can perform these changes, by calling some of the following functions.

  • glMatrixMode(x); - Where x is either GL_PROJECTION_MATRIX or GL_MODELVIEW_MATRIX
  • glLoadIdentity(); - "Resets" the current selected matrix.
  • glTranslate*(x, y, z);
  • glRotate*(angle, x, y, z);
  • glScale*(x, y, z);

Though, if you're using modern OpenGL then don't use the above (which you also really can't then). Instead you want to calculate all the matrix transformations yourself and pass them to your shader. If you don't want to calculate all those advanced matrix operations yourself, you can get something like GLM (OpenGL Mathematics).

0
user106688 On

I am not an OpenGL programmer. My interests mainly lies in algebraic projective geometry.

Per my understanding, The geometric meaning of the projection matrix in the OpenGL function GLFrustum(), which was explained in the official guide of OpenGL (the nineth edition of the book, OpenGL programming guide-- the official guide to learning OpenGL), from an algebraic point of view, actually corresponds to many geometric meanings that are unluckily different from what the authors expected.

A significant difference between them are: 1. in the official guide, the authors are illustrating a compound linear transform with one of its factors as central projection, so the final compound perspective projecction matrix should be a singular or degenerated matrix; 2. while still in the official guide, at the appendix, the GLFrustum() perspective projection matrix is a nonsingular 4 times 4 square matrix!

Note that: The authors are trying to explain a nonsingular matrix into a theoretically singular one!

The following matrix decomposition (not unique) corresponds to one of the geometric meanings of the nonsingualr GLFrustum() matrix: enter image description here

LaTeX code of the formulation:

$$n\underbrace{\color{blue}\left[
\begin{array}{cccc}
 1 & 0 & 0 & 0 \\[12pt]
 0 & 1 & 0 & 0 \\[12pt]
 0 & 0 &\dfrac{n+f}{(n-f) n} & 0 \\[12pt]
 0 & 0 & 0 & 1 \\[12pt]
\end{array}
\right]}_{\color{red}(1)}\cdot \underbrace{\color{blue}\left[
\begin{array}{cccc}
\dfrac{ -2}{l-r} & 0 & 0 & \dfrac{l+r}{l-r} \\[12pt]
 0 & \dfrac{ -2}{b-t} & 0 & \dfrac{b+t}{b-t} \\[12pt]
 0 & 0 & 1 & 0 \\[12pt]
 0 & 0 & 0 & 1 \\[12pt]
\end{array}
\right]}_{\color{red}(2)}\cdot\underbrace{\color{blue}\left[
\begin{array}{cccc}
 1 & 0 & 0 & 0 \\[12pt]
 0 & 1 & 0 & 0 \\[12pt]
 0 & 0 & 1 & 0 \\[12pt]
 0 & 0 & -\dfrac{1}{n} & 1 \\[12pt]
\end{array}
\right]}_{\color{red}(3)}\cdot\underbrace{\color{blue}\left[
\begin{array}{cccc}
 1 & 0 & 0 & 0 \\[12pt]
 0 & 1 & 0 & 0 \\[12pt]
 0 & 0 & 1 & 1 \\[12pt]
 0 & 0 & 0 & \dfrac{1}{n} \\[12pt]
\end{array}
\right]}_{\color{red}(4)}\cdot\underbrace{\color{blue}\left[
\begin{array}{cccc}
 1 & 0 & 0 & 0 \\[12pt]
 0 & 1 & 0 & 0 \\[12pt]
 0 & 0 & 1 & 0 \\[12pt]
 0 & 0 & 0 & \dfrac{2 n f}{f+n} \\[12pt]
\end{array}
\right]}_{\color{red}(5)} $$

All of the above matrix factors except for No. (2), have their geoemtric meaning clearly redefined in Unified Framework of Elementary Geometric Transformations. If you choose this factorization as the geometric meaning explanation of the GLFrustum() perspective projection matrix, you will have to make sure any computation or transforms you are doing in your code are consistent to its geometric meaning.

So when you are programming with OpenGL GLFrustum(), probably may have to compare with what has been illustrated in the official guide and what the GLFrustum() perspective projection matrix really means from the view point of pure algebraic projective geometry, and use any one of your own.