problem with setting up intrinsic matrix

Ok, this might get complicated but I’ll do my best to explain as good as I can:

I have an OpenGL (JOGL) scene consisting of a white plane with 4 colored orbs on it (red, green, blue, yellow). My assignment is simple: given the world coordinates of the orbs, calculate the world position of the camera from which the orbs are viewed at time t.

For this I am using the Levenberg-Marquardt algorithm (no need to look it up, not relevant to this question), which basically is a trial and error method that requires me to identify the camera coordinates of the (centers of the) orbs for every iteration in order to calculate the result with the smallest offset, given a set of values.

I have already implemented the LM algorithm, no problems there. However, this algorithm only gives me a possible solution, it is my job to find out if this solution is correct or not. In my case, this means to transform 4 points (the centers of the orbs) from world coordinate system into image coordinate system, using a set of parameters given by the algorithm. And this last part is what’s troubling me for a week or so now.

It seems that, no matter what I do, I can’t get this stuff right. The world coordinates of the points are known and the camera translation and orientation are given by the algorithm. The problem is that I don’t have the correct intrinsic matrix to do this transformation. My results should be something like this:

1 = 175.0, 267.0
2 = 198.0, 311.0
3 = 291.0, 266.0
4 = 385.0, 289.0

so basically 4 (x,y) coordinate pairs in a 580x560 window.

Here are some of the things I tried:

If I try to identify the intrinsic matrix that OpenGL uses to render my view using this code

float stack[] = new float[16];
gl.glGetFloatv(gl.GL_PROJECTION_MATRIX, stack, 0);

I get the following result, which is about as wrong as it can possibly get:

{2,  0,  0,  0} 
{0,  2,  0,  0} 
{0,  0,  1,  0}

results =
x = 0.8, y = 0.64
x = 1.52, y = 0.56
x = 1.2, y = 0.64
x = 0.88, y = 0.48

I also tried loading my own intrinsic matrix using this code

float[] intrinsic = makeProjectionMatrix(); // fill with predetermined values
gl.glLoadMatrixf( projectionMatrix, 0 );

gl.glScalef(2/width, 2/height, 1);

but this screws up my view so bad I can’t even see my plane anymore or it removes all but one of my orbs from the plane, making this solution completely useless… This could mean that I’m not using the correct values, but I’ll honestly admit that I don’t know enough about this stuff to actually know what I should or shouldn’t use here. I’ve read extensively on the subject, though I haven’t been making a lot of progress, unfortunately.

Any help on this subject would be much appreciated, I don’t have a clue what to do.

Why is glGetFloatv taking three parameters? It normally takes two parameters.

Where you say, “I get the following result”, you show a matrix that is missing the fourth row.

My (possibly wrong) understanding of the projection matrix is:

  1. It maps the depth range to a 0.0 to 1.0 range
  2. It maps the X and Y screenspace coordinates to -1.0 to 1.0 range. These are commonly called NDC’s (Normalized Device Coordinates)
  3. It actually needs a 4x4 matrix because it uses the W coordinate to give us a sort of “divide by z” functionality, scaled as mentioned above. (I hear the math purists shuddering at my gross overgeneralizations :slight_smile:

The output of the projection transform is a 4-element vector: x, y, z, w.

The screenspace values are calculated from:

x/w, y/w, z/w, 1

So if you were expecting pixel coordinates, you then have to scale up the X and Y to be pixel coordinates.


Because it’s Java :slight_smile:

That’s kinda the issue. The projection matrix is 4x4, but for the calculations I wanted to do, I needed the 3x3 intrinsic camera matrix with an added column of zeros in the back, giving me the 3x4 I posted. My question was basically: how to get to this intrinsic matrix, starting from the projection matrix.

I actually fixed my problem yesterday: I worked around it by taking another approach. I basically replicated the OpenGL transformation (found here) which gives me the results I need.

I still don’t know exactly how to do what I initially wanted to do, but as far as I’m concerned, this problem is solved. Thanks for helping out :slight_smile: