2013-02-11 27 views
3

我有一組從點掃描儀獲取的點(3D)。樣本數據可以在這裏找到:http://pastebin.com/RBfQLm56如何使用相機參數在OpenGL中正確設置投影和模型視圖矩陣

我也有掃描儀的參數如下:

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] 

我試圖使這些點的正確使用的OpenGL,但渲染看起來不正確的。什麼是設置openGL投影和模型視圖矩陣的正確方法?這是我目前正在做的 -

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) 

正在使用的功能有:

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) 

然後,我只呈現點(粘貼片段):

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

你得到的矩陣,最值得注意的是在你的問題中最後一個是OpenGL中的投影和模型視圖的組成,也稱爲Modelview投影,即

MVP = P·男

只要你不感興趣的進行照明計算,你可以只使用在頂點着色器,即

#version 330 

uniform mat4 MVP; 
in vec3 position; 

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

BTW,OpenGL和可能的庫您「再使用爲好,使用列優先順序,即在內存中的元素的順序是

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

有啥寫的源代碼必須被認爲是‘換位’(當然不是)。由於你寫的矩陣遵循相同的方案,你可以把它放入制服中。剩下的唯一問題就是範圍掃描儀使用的NDC空間的邊界。但是這可以通過應用額外的矩陣來處理。 OpenGL使用範圍[-1,1]^3,所以最糟糕的情況是,如果它在其他流行的NDC範圍[0,1]^3中,您會看到您的幾何體被擠壓到左上角如果Z軸進入另一個方向,可能會將其翻轉過來。試試吧,我會說它已經與OpenGL相匹配了。

無論如何,如果你想使用它與照明,你必須分解成投影和模型視圖部分。說起來容易做起來難,但一個好的出發點是對左上方的3×3子矩陣進行正交歸一化處理,產生模型視圖'M'的旋轉部分。然後你必須找到一個矩陣P,當左乘以M得到原始矩陣。這是一個超定的線性方程組,所以高斯 - 約旦方案可以做到這一點。如果我沒有完全弄錯,那麼你已經以相機矩陣的形式得到了什麼,或者是已分解的M或P(我會去M)。

一旦你得到了,你可能想要將翻譯部分(第4列)也放入模型視圖矩陣中。

+0

非常感謝datenwolf。就矩陣而言,相機矩陣(第一個)是固有相機參數,第三個(相機參考)是外在相機參數。我假設使用固定的OpenGL管道,設置矩陣的最簡單方法是什麼?我想有一種選擇是在着色器中乘以這些參數,但如果使用照明? – mrkulk 2013-02-11 21:05:19

+0

如果你想工作照明,你必須按照概述分解矩陣。你有關於我可以閱讀的矩陣的一些文檔嗎?技術上來說,照明的工作,你只需要提取正交歸一化的左上方3×3來轉換法線。不幸的是,這隻適用於可編程流水線,因爲固定功能流水線對矩陣做了某些假設。所以對於固定功能流水線,您必須對其進行分解。正交歸一化的部分是,然後進入模型視圖,補充部分將是投影。 – datenwolf 2013-02-11 22:07:06

+0

還缺少適當設置近和遠的剪輯平面。 – datenwolf 2013-02-11 22:07:27