Decompose projection matrix44 to left, right, bottom, top, near and far boundary values

4k Views Asked by At

Can any one help me to get left, right, bottom, top, near and far boundary values from projection matrix44?

3

There are 3 best solutions below

2
On

First, you could look how those matrices are defined for corresponding calls to glOrtho and glFrustum (or similar functions from your framework). The next steps depend on the kind of projection, being either orthographic (e.g. from glOrtho) or perspective (e.g. from glFrustum or gluPerspective), which can be decided by looking at the 3rd column.

Now for an orthographic matrix it is quite easy to get to the two equations:

right - left = 2 / m11
right + left = -2 * m14 / m11

From these you can quite easily compute right = (1-m14) / m11 and left = right - 2/m11 (you may recheck for any errors made during my mental arithmetics). And similar for the other two pairs of parameters (pay attention to the sign of m33).

For a perspective projection you should first compute near and far using m33 and m34. Then you can compute right/left and bottom/top similar to the above case, but using the computed near value.

So all in all, once you know the formulas for the matrices based on the parameters, it really comes down to just a bunch of simple 2x2 equation systems easy to solve. A more interesting question would be, why you actually need to compute these parameters from a projection matrix. If you really need them, you should just store them (as you are the one who constructs the matrix, anyway). Otherwise it sounds like another instance of using OpenGL for more things (like scene management) than it's actually intended for, being just a simple drawing API.

1
On

Here are the resolutions of the equation systems Christian Rau referred to :

For an orthographic matrix :

near   =  (1+m34)/m33;
far    = -(1-m34)/m33;
bottom =  (1-m24)/m22;
top    = -(1+m24)/m22;
left   = -(1+m14)/m11;
right  =  (1-m14)/m11;

For a perspective matrix :

near   = m34/(m33-1);
far    = m34/(m33+1);
bottom = near * (m23-1)/m22;
top    = near * (m23+1)/m22;
left   = near * (m13-1)/m11;
right  = near * (m13+1)/m11;

You can replace the values m11, m12, etc., by the formulas defined in the documentation for glOrtho and glFrustum to check it's correct.

0
On

For future reference, I copy here below the values of near, far, etc. in C++ for OpenGL with 0-indexed column-major projection matrix:

float near = m_projectionMatrix[3][2] / (m_projectionMatrix[2][2] - 1.0f);
float far = m_projectionMatrix[3][2] / (m_projectionMatrix[2][2] + 1.0f);
logStderr(VERBOSE, "near, far %5.2f, %5.2f...\n", near, far);

float nearBottom = near * (m_projectionMatrix[2][1] - 1) / m_projectionMatrix[1][1];
float nearTop = near * (m_projectionMatrix[2][1] + 1) / m_projectionMatrix[1][1];
float nearLeft = near * (m_projectionMatrix[2][0] - 1) / m_projectionMatrix[0][0];
float nearRight = near * (m_projectionMatrix[2][0] + 1) / m_projectionMatrix[0][0];
logStderr(VERBOSE, "nearLeft, nearRight, nearTop, nearBottom %5.2f, %5.2f, %5.2f, %5.2f...\n", nearLeft, nearRight, nearTop, nearBottom);

float farBottom = far * (m_projectionMatrix[2][1] - 1) / m_projectionMatrix[1][1];
float farTop = far * (m_projectionMatrix[2][1] + 1) / m_projectionMatrix[1][1];
float farLeft = far * (m_projectionMatrix[2][0] - 1) / m_projectionMatrix[0][0];
float farRight = far * (m_projectionMatrix[2][0] + 1) / m_projectionMatrix[0][0];
logStderr(VERBOSE, "farLeft, farRight, farTop, farBottom %5.2f, %5.2f, %5.2f, %5.2f...\n", farLeft, farRight, farTop, farBottom);