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 A^{T}A is invertible? (2) Linear Algebra

Why A^{T}A has the inverse Let me explain why A^{T}A has the inverse, if the columns of A are independent. First, if a matrix is n by n, and all the columns are independent, then this is a square full rank matrix. Therefore, there is the inverse. So, the problem is when A is a m by n, rectangle matrix.  Strang's explanation is based on null space. Null space and column space are the fundamental of the linear algebra. This explanation is simple and clear. However, when I was a University student, I did not recall the explanation of the null space in my linear algebra class. Maybe I was careless. I regret that... Explanation based on null space This explanation is based on Strang's book. Column space and null space are the main characters. Let's start with this explanation. Assume  x  where x is in the null space of A .  The matrices ( A^{T} A ) and A share the null space as the following: This means, if x is in the null space of A , x is also in the n...

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...

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) .