So I was testing my matrix class and the results look questionable and the inverted matrix isn't returning the vertex to it's original value (a seperate issue). Given a perspective projection at 45 degrees with a near of 1 and a far of 1000, the camera at the orgin looking down z and a vertext along z axis at 0, 1 and 1000, What would their resulting depths be?

Recommended Answers

All 10 Replies

So after a lengthy debug and fixing a few issues, I've narrowed down the bugs/ things I don't understand to the projection matrix.

Here's what I'm getting:
Looking from the origin in the vector <1,1,1> with a ratio of 1 a near of 1 and a far of 1000:
input vertex: (100, 100, 100)
restult: (0.000000, 0.000000, 171.549835)
multiplying result to inverse matrix: (0.577350, 0.577350, 0.577350) <- same direction but wrong magnitude...

So below are some assumptions and code; let me know if any of it is wrong:

P = projection matrix
M = model view matrix
Vm = vertex in "world"
Vs = screen vertex

Vs = P x M x Vm
Vm = (P x M)^-1 x Vs

        Col. Major   
      |AA BA CA DA|  
      |AB BB CB DB|  
      |AC BC CC DC| 
      |AD BD CD DD|  

   void APCamera::setPerspective(GMFloat_t fov, GMFloat_t aspect, GMFloat_t near, GMFloat_t far)
      GMFloat_t difZ = near - far;

      GMFloat_t *data;

      mProjection->clear(); //set to identity matrix
      data = mProjection->getData();

      GMFloat_t v = 1.0f / tan(fov / 2.0f);

      data[_AP_MAA] = v / aspect;
      data[_AP_MBB] = v;
      data[_AP_MCC] = (far + near) / difZ;
      data[_AP_MCD] = -1.0f;
      data[_AP_MDD] = 0.0f;
      data[_AP_MDC] = 2.0f * far * near/ difZ;

      mRatio = aspect;

On a first glance, i difz should be positive, so far - near, also do you have the fov in radians? Also, are data[_AP_MCC] and data[_AP_MDC] been multiplied by -1?. It could also be that the values inside the brakets do not correspond to the right matrix position, i doubt it as the direction of the resulting vector is correct (taking your word for it) and the only incosistentcy is the magnitud

here is how to derive the matrix using math http://www.scratchapixel.com/lessons/3d-advanced-lessons/perspective-and-orthographic-projection-matrix/perspective-projection-matrix/
you should get familiar with how to do that so the code makes more sence

So fov is in radians and the reason data[_AP_MCC] and data[_AP_MDC] are not multiplied by -1 is because diffz is swapped.Thanks for the link, it may point to the flaw. Please let me know if anything else stands out.

If you are computing Vs from Vm, and then computing Vm back from Vs, and the two don't match, then it means that your matrix inversions are not correct. Regardless of whether you defined your matrices correctly with regard to getting a correct modelview + projection transformation, the transformation back and forth should always work if you inverted the matrices correctly.

To verify that you inverted your matrices correctly, just try to do (P x M)^-1 x P x M which should result in the identity matrix (all zero, expect all 1 on diagonal). If that's not the case, then show us your matrix inversion code and we might be able to point out the problem.

So I have already done that and I've gotten the identity matrix back. So I'm puzzled with the miss-match and shouldn't the depth be between 0 and 1 (if within the frustum)?

Also, I did it to a rotation matrix by itself, I was able to rotate a vector and undo it and multiply that inverted matrix to the original rotation matrix and get the identity back. So it's all pointing to the projection function, but nothing is standing out.

shouldn't the depth be between 0 and 1 (if within the frustum)?

The projection matrix takes the vector to the so-called "clip" coordinates, not the screen coordinates. See the last section of this complete explanation.

The depth value will only be between 0 and 1 once you have done the division by the 4th component of the vector. In other words, you start with the "world" vector:

Vm = | Xm |
     | Ym |
     | Zm |
     | 1.0|

which you then multiply by PxM, to get the "clip" vector "Vc" as this:

Vc = P x M x Vm
Vc = | Xc |
     | Yc |
     | Zc |
     | Wc |

And then, you can get the "screen" vector (where x and y are between -1 and 1, and z is from 0 to 1) as so:

Vs = | Xc / Wc |
     | Yc / Wc |
     | Zc / Wc |

You can recover Vm from Vc by the simple (P x M)^-1 transformation, but recovering Vm from Vs is a bit harder (non-linear), but not impossible either, of course.

So, that partly clears up some confusion. The one thing that has me confused is that I thought W is 1 if it's a vertex and 0 when it's a vector. Am I confusing this with something else?

So assuming that the output looks right after these adjustments, I should just be able to feed this into opengl as the projection matrix (since this is gluperspective(...))?

The one thing that has me confused is that I thought W is 1 if it's a vertex and 0 when it's a vector.

That's true for vectors in world coordinates and throughout the modelview transformation(s). However, at the last step (projection), they use the fourth component in this special way to be able to compute those normalized screen coordinates. And the projection matrix only deals with vertices anyways (no vectors), because the point of that matrix is to transform a position (vertex) from a "normal" 3D orthogonal coordinate system into the special projected coordinate system, i.e., the "clip" coordinates, which are then normalized using the fourth component.

I should just be able to feed this into opengl as the projection matrix (since this is gluperspective(...))?

Yes. The projection matrix in OpenGL is exactly that, maps from world coord. to clip coord., and the division by the fourth component will be done by OpenGL internally, after the projection matrix has been applied. So, you projection matrix should be good to use directly (e.g., with glMatrixMode(GL_PROJECTION); glLoadMatrixf(mProjection->getData());).

So it looks like getting the inverse of the perspective works, but now I'm having trouble with the Orthographic view, which is weird as it's almost a scalar matrix (assuming left,righ top,bottom are equal in magnitude). So I keep getting about +/-0.4.. on the edges no matter what I set, even if it's (-100, 100) or (-1,1). Any clue what I'm missing (I've tried both having the fourth index as 1 and as the result of the non-inverse)?

Gosh, read the links that were sent to you. It's all explained in there...

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, learning, and sharing knowledge.