Skip to main content

How to get the camera parameters from OpenGLperspective/modelview matrix? (1)

Abstract

This is a computer graphics and programming story. While ago, I wrote about a matrix that is generated by a OpenGL function, gluLookat. (http://shitohichiumaya.blogspot.de/2011/01/what-matrix-glulookat-generates-1.html) Why did I write that story? Because I was developing a renderer that is independent from the OpenGL, but some point, I need to overlay OpenGL generated image and our renderer's image. I think not a lot of people need to write a own renderer, therefore, this blog entry maybe not so much refereed. However, there are quite a lot of people visited this page. I don't know what kind of people visiting this pages, I am a bit surprised. This time, our customer has a special system and they need to compute the inverse of the OpenGL functions. Their input is OpenGL's Projection/Modelview matrix and the output is camera parameters. This is more special cases, but, the problem itself may be interested in.

Introduction

There are interesting visualization system in this world. This time, my customer told us, ``We don't know where our camera is, but we know the matrices. Could you compute your rendering system's camera parameter out of them?'' I was a bit surprised this story, how a system which can manipulate camera doesn't know the camera position? But the story is not so simple. This software is a commercial huge system. One of the software layer can not see the camera parameter because it is simply the system is complex. But they use OpenGL and it is possible to access the perspective/modelview matrices at their software layer. Therefore, they just asked us to extract the camera parameters from these matrices.

This is quite a rare case, though, it is also an interesting puzzle: given OpenGL projection/modelview matrices, how to get the camera parameters? Maybe there are a few people who find this interesting.

Get camera parameter from the OpenGL perspective matrix.

This section, we talk about how to get perspective camera parameters from the OpenGL perspective matrix.

In OpenGL, gluPerspective generates the perspective matrix. (Please refer the OpenGL manual in details.)

void gluPerspective(GLdouble fovyd,  GLdouble aspect,
                    GLdouble zNear, GLdouble zFar);
  • fovyd: Specifies the field of view angle, in degrees, in the y direction. Note: this is degrees, not radian.
  • aspect: Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height).
  • zNear: Specifies the distance from the viewer to the near clipping plane (always positive).
  • zFar: Specifies the distance from the viewer to the far clipping plane (always positive).
According to the OpenGL manual, the generated perspective matrix is the following.

\begin{eqnarray*}
 \left[
  \begin{array}{cccc}
   \frac{fr}{asp}  & 0  & 0 & 0  \\
   0               & fr & 0 & 0  \\
   0               & 0  & \frac{z_f + z_n}{z_n - z_f} & -1 \\
   0               & 0  & \frac{2 z_f z_n}{z_n - z_f} & 0  \\
  \end{array}
  \right]
\end{eqnarray*}
where \(fr = \frac{1}{\tan(\frac{fovy}{2})}\), \(fovy\) is in radian of  \(fovyd\), \(asp\) is aspect ratio, \(z_n\) is the near clipping plane distance, \(z_f\) is the far clipping plane distance. For simplicity, we rewrite the perspective matrix as the following.
\begin{eqnarray*}
 \left[
  \begin{array}{cccc}
   aa & 0  & 0  & 0  \\
   0  & bb & 0  & 0  \\
   0  & 0  & cc & -1 \\
   0  & 0  & dd & 0  \\
  \end{array}
  \right]
\end{eqnarray*}
\begin{eqnarray*}
 asp  &=& \frac{bb}{aa}\\
 fovy &=& 2 \arctan(\frac{1}{bb})\\
 z_f  &=&\frac{c-1}{c+1} z_n
\end{eqnarray*}
Here, let \(kk = \frac{c-1}{c+1}\), we get
\begin{eqnarray*}
 z_n &=& \frac{dd(1-kk)}{2k}\\
 z_f &=& \frac{dd(1-kk)}{2}.
\end{eqnarray*}
Note \(z_n \neq 0\).



My implementation example of those in C++ is the following.


/// get perspective camera parameters
/// from the OpenGL projection matrix
///
/// \param[out] fovy_rad     field of view in radian
/// \param[out] aspect_ratio aspect ratio
/// \param[out] clip_min     clipping min distance
/// \param[out] clip_max     clipping max distance
void gl_get_camera_parameter_from_perspective_matrix(
    double & fovy_rad,
    double & aspect_ratio,
    double & clip_min,
    double & clip_max)
{
    GLdouble mat[16];
    glGetDoublev(GL_PROJECTION_MATRIX, mat);

    GLdouble const aa = mat[0];
    GLdouble const bb = mat[5];
    GLdouble const cc = mat[10];
    GLdouble const dd = mat[14];

    aspect_ratio = bb / aa;
    fovy_rad     = 2.0f * atan(1.0f / bb);

    GLdouble const kk = (cc - 1.0f) / (cc + 1.0f);
    clip_min = (dd * (1.0f - kk)) / (2.0f * kk);
    clip_max = kk * clip_min;
}

For simplicity, I omitted the division by zero check. Of course when OpenGL has been correctly set up, then this should be OK. Though, personally I would put some assertions.

Comments

Popular posts from this blog

Why parallelogram area is |ad-bc|?

Here is my question. The area of parallelogram is the difference of these two rectangles (red rectangle - blue rectangle). This is not intuitive for me. If you also think it is not so intuitive, you might interested in my slides. I try to explain this for hight school students. Slides:  A bit intuitive (for me) explanation of area of parallelogram  (to my site, external link) . 

Geometric Multiplicity: eignvectors (2)

If eigenvectors of a matrix A are independent, it is a happy property. Because the matrix A can be diagonalized with a matrix S that column vectors are eigenvectors of A . For example, Why this is a happy property of A? Because I can find A's power easily. A^{10} is not a big deal. Because Λ is a diagonal matrix and power of a diagonal matrix is quite simple. A^{10} = SΛ^{10} S^{-1} Then, why if I want to compute power of A ? That is the same reason to find eigenvectors. Eigenvectors are a basis of a matrix. A matrix can be represented by a single scalar. I repeat this again. This is the happy point, a matrix becomes a scalar. What can be simpler than a scalar value. But, this is only possible when the matrix S's columns are independent. Because S^{-1} must be exist. Now I come back to my first question. Is the λ's multiplicity related with the number of eigenvectors? This time I found this has the name. Geometric multiplicity (GM): the number of in...

Gauss's quote for positive, negative, and imaginary number

Recently I watched the following great videos about imaginary numbers by Welch Labs. https://youtu.be/T647CGsuOVU?list=PLiaHhY2iBX9g6KIvZ_703G3KJXapKkNaF I like this article about naming of math by Kalid Azad. https://betterexplained.com/articles/learning-tip-idea-name/ Both articles mentioned about Gauss, who suggested to use other names of positive, negative, and imaginary numbers. Gauss wrote these names are wrong and that is one of the reason people didn't get why negative times negative is positive, or, pure positive imaginary times pure positive imaginary is negative real number. I made a few videos about explaining why -1 * -1 = +1, too. Explanation: why -1 * -1 = +1 by pattern https://youtu.be/uD7JRdAzKP8 Explanation: why -1 * -1 = +1 by climbing a mountain https://youtu.be/uD7JRdAzKP8 But actually Gauss's insight is much powerful. The original is in the Gauß, Werke, Bd. 2, S. 178 . Hätte man +1, -1, √-1) nicht positiv, negative, imaginäre (oder gar um...