How to set projection matrices and models correctly in OpenGL using camera parameters

I have a set of points (3D) taken from the range of the scanner. Sample data can be found here: http://pastebin.com/RBfQLm56

I also have the following options for the scanner:

camera matrix
[3871.88184, 0, 950.736938;
  0, 3871.88184, 976.1383059999999;
  0, 0, 1]



distortion coeffs
[0.020208003; -1.41251862; -0.00355229038; -0.00438868301; 6.55825615]



camera to reference point (transform)

[0.0225656671, 0.0194614234, 0.9995559233, 1.2656986283;

  -0.9994773883, -0.0227084301, 0.0230060289, 0.5798922567;

  0.0231460759, -0.99955269, 0.0189388219, -0.2110195758;

  0, 0, 0, 1]

      

I'm trying to get these points correct using opengl, but the rendering doesn't look like this. What is the correct way to set up the OpenGL projection and model view matrix? This is what I am doing now -

znear = 0.00001
zfar =  100
K = array([[3871.88184, 0, 950.736938],[0, 3871.88184, 976.1383059999999],[0, 0, 1]])
Rt =array([[0.0225656671, 0.0194614234, 0.9995559233, 1.2656986283],[-0.9994773883, -0.0227084301, 0.0230060289, 0.5798922567],[0.0231460759, -0.99955269, 0.0189388219, -0.2110195758]])
ren.set_projection(K,zfar,znear)
ren.set_projection_from_camera(Rt)

      

Function used:

def set_projection(self,K,zfar,znear):
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    f_x = K[0,0]
    f_y = K[1,1]
    c_x = K[0,2]
    c_y = K[1,2]
    fovY = 1/(float(f_x)/height * 2);
    aspectRatio = (float(width)/height) * (float(f_y)/f_x);
    near = zfar
    far = znear
    frustum_height = near * fovY;
    frustum_width = frustum_height * aspectRatio;
    offset_x = (width/2 - c_x)/width * frustum_width * 2;
    offset_y = (height/2 - c_y)/height * frustum_height * 2;
    glFrustum(-frustum_width - offset_x, frustum_width - offset_x, -frustum_height - offset_y, frustum_height - offset_y, near, far);


def set_modelview_from_camera(self,Rt):
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    Rx = array([[1,0,0],[0,0,-1],[0,1,0]])
    R = Rt[:,:3]
    U,S,V = linalg.svd(R)
    R = dot(U,V)
    R[0,:]=-R[0,:]
    t=Rt[:,3]
    M=eye(4)
    M[:3,:3]=dot(R,Rx)
    M[:3,3]=t
    M=M.T
    m=M.flatten()
    glLoadMatrixf(m)

      

Then I just output the points (by inserting the snippet):

def renderLIDAR(self,filename):
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    glPushMatrix();

    glEnable(GL_DEPTH_TEST)
    glClear(GL_DEPTH_BUFFER_BIT)
    glPointSize(1.0)
    f = open(filename,'r')
    f.readline() #Contains number of particles
    for line in f:
        line = line.split(' ')
        glBegin(GL_POINTS)
        glColor3f (0.0,1.0,0.0); 
        x = float(line[0])
        y = float(line[1])
        z = float(line[2])
        glVertex3f(x,y,z)
        #print x,y,z
        glEnd()

    glPopMatrix();

      

+3


source to share


1 answer


The matrices you return, primarily the last one in your question, is what in OpenGL is the composition of the projection and view of the model, also called Modelviewprojection, i.e.

MVP = P M

Until you are interested in doing light calculations, you can use exactly that in the vertex shader, i.e.

#version 330

uniform mat4 MVP;
in vec3 position;

void main()
{
    gl_Position = MVP * vec4(position, 1);
}

      

BTW, OpenGL, and maybe the library you are using use basic column order i.e. order of items in memory



0 4 8 c
1 5 9 d
2 6 a e
3 7 b f

      

therefore, what is written in the source code should be considered "transposed" (of course it is not). Since the matrix you wrote follows the same pattern, you can simply put it in the form as it is. The only question that remains is about the boundaries of the NDC space used by the range scanner. But this could be taken care of with an additional matrix. OpenGL uses the range [-1, 1] ^ 3, so the worst thing that can happen is that if it's in the other popular NDC range [0, 1] ^ 3, you'll see your geometry just shrink at the top the left corner is the rotation angle of your window and possibly rotated "inside out" if the Z-axis goes into a different direction. Just try it, I would say it is already OpenGL compliant.

Anyway, if you want to use it backlit, you have to decompose it into projection and part of the model. Easier said than done, but a good starting point is the orthonormalization of the upper left 3 × 3 submatrix, which gives the rotational part of the M 'model. Then you need to find the matrix P, which, when multiplied by M on the left, gives the original matrix. This is an overdetermined set of linear equations, so a Gauss-Jordan scheme can do it. And if I'm not entirely mistaken, what you already got in the form of this camera matrix is ​​either a decomposed M or P (I would go for M).

Once you've got this, you might want to get the translational part (4th column) into the model view matrix.

+3


source







All Articles