Search code examples
c++openglcameraprojectioncamera-calibration

Intrinsic Camera Matrix to OpenGL Projection. Unexpected Scaling Factor


I am having quite a hard time fixing some problems regarding AR projection matrices. My base is the calibrated camera matrix. I'm trying to retrieve the projection matrix for OpenGL projection. I pretty much followed this article: http://ksimek.github.io/2013/06/03/calibrated_cameras_in_opengl/ But the result is too small and it has an amplified offset depending on the transformation matrix. Since it's too small, I changed the parameters back and forth to figure out what the problem is.

Following the correct calculation described in the article:

//p is the intrinsic camera matrix as you know it
glm::mat4x4 perspective, ndc;

perspective[0][0] = p[0][0];
perspective[0][1] = 0;
perspective[0][2] = 0;
perspective[0][3] = 0;
perspective[1][0] = 0;
perspective[1][1] = p[1][1];
perspective[1][2] = 0;
perspective[1][3] = 0;
perspective[2][0] = -p[2][0];
perspective[2][1] = -p[2][1];
perspective[2][2] = (gnear+gfar);
perspective[2][3] = -1;
perspective[3][0] = 0;
perspective[3][1] = 0;
perspective[3][2] = gnear*gfar;
perspective[3][3] = 0;


ndc[0][0] = 2.0f/(width);
ndc[0][1] = 0;
ndc[0][2] = 0;
ndc[0][3] = 0;
ndc[1][0] = 0;
ndc[1][1] = 2.0f/height;
ndc[1][2] = 0;
ndc[1][3] = 0;
ndc[2][0] = 0;
ndc[2][1] = 0;
ndc[2][2] = -2.0f/(gfar-gnear);
ndc[2][3] = 0;
ndc[3][0] = -((width/width));
ndc[3][1] = -((height/height));
ndc[3][2] = -((gfar+gnear)/(gfar-gnear));
ndc[3][3] = 1;

glm::mat4x4 proj2 = ndc*perspective;

This does not exactly work for me.

I did these two changes (adding the 0.5f factor):

perspective[2][2] = (gnear+gfar)*0.5f;
perspective[3][2] = gnear*gfar*0.5f;

This works pretty well to a degree. I'm doing marker tracking currently and the resulting marker model aligns perfectly well with the actual real world marker. Sadly, there appears to be a slight error in the mapping of the transformation distance. The appearance is that the models are not scaled correctly, depending on the distance to the origin. I go away from the marker, the models are too small. If I reach a certain point the models are okay. After this point, they are too large. I repeat: The marker model appears to be mapped correctly all the time.

I checked if I made any mistakes regarding the initial error in the scaling factor. But I couldn't find anything.

What could cause the need for this scaling?

I understand that this question is almost impossible to answer due to lack of information and code, but maybe somebody has an idea.


Solution

  • Well, from the experienced impact of the near and far plane you can definetly derive, that there is something seriously wrong. What is wrong, you cannot deduct. In my case, I had a combination of different matrix math frameworks. One framework works column major, the other one row major. Therefore I transposed the matrices several times back and forth leading to an inversion of the multiplication order. I removed one framework(Qt) and now the described derivation of the projection matrix works. Thank you a lot stackoverflow. You always help me to formulate questions, so I can find the answer myself.