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

3

7

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

Heartbreaker answered 31/5, 2012 at 8:52 Comment(0)
P
10

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.

Protective answered 17/10, 2012 at 3:26 Comment(1)
FYI this answer is using (1-indexed) row major matrix coords, OpenGL uses column major by default. If you don't transpose the coords, m34 will be a constant value.Kola
B
3

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.

Ballesteros answered 31/5, 2012 at 15:22 Comment(2)
Actually I have to do this(#10810860). Help me to achieve.Heartbreaker
@Heartbreaker I don't have any experience with those libraries you're talking about, but as a general information you might not have known, you don't neccessarily need to extract the parameters of a glOrtho or glFrustum call from a matrix to get the same projection matrix into OpenGL. You can just use the glLoadMatrix or glMultMatrix functions to input matrices directly. Not sure if it's that what you want to achieve, as I didn't understand this other question completely.Ballesteros
F
3

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);
Floribunda answered 29/6, 2018 at 8:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.