2015-02-09 110 views
1

我一直在試圖讓我的鼠標座標轉換成OpenGL場景中的三維空間座標。現在,我的預測有點混亂(我認爲),並且當我在場景中移動時,似乎沒有充分考慮我的「相機」。爲了檢查這一點,我畫了一條線。座標轉換和投影問題

我調整大小功能:

void oglWidget::resizeGL(int width, int height) 
    { 
     if (height == 0) { 
      height = 1; 
     } 
     pMatrix.setToIdentity(); 
     pMatrix.perspective(fov, (float) width/(float) height, -1, 1); 
     glViewport(0, 0, width, height); 
    } 

我的渲​​染功能(paintGl())去如下:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 
QMatrix4x4 mMatrix; 
QMatrix4x4 vMatrix; 

QMatrix4x4 cameraTransformation; 
cameraTransformation.rotate(alpha, 0, 1, 0); 
cameraTransformation.rotate(beta, 1, 0, 0); 

QVector3D cameraPosition = cameraTransformation * QVector3D(camX, camY, distance); 
QVector3D cameraUpDirection = cameraTransformation * QVector3D(0, 1, 0); 
vMatrix.lookAt(cameraPosition, QVector3D(camX, camY, 0), cameraUpDirection); 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity();  
gluLookAt(cameraPosition.x(), cameraPosition.y(), cameraPosition.z(), camX, camY, 0, cameraUpDirection.x(), cameraUpDirection.y(), cameraUpDirection.z()); 

shaderProgram.bind(); 
shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix); 
shaderProgram.setUniformValue("texture", 0); 


for (int x = 0; x < tileCount; x++) 
{ 
    shaderProgram.setAttributeArray("vertex", tiles[x]->vertices.constData()); 
    shaderProgram.enableAttributeArray("vertex"); 
    shaderProgram.setAttributeArray("textureCoordinate", textureCoordinates.constData()); 
    shaderProgram.enableAttributeArray("textureCoordinate"); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tiles[x]->image.width(), tiles[x]->image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tiles[x]->image.bits()); 
    glDrawArrays(GL_TRIANGLES, 0, tiles[x]->vertices.size()); 
} 
shaderProgram.release(); 

並創建我雷:

GLdouble modelViewMatrix[16]; 
GLdouble projectionMatrix[16]; 
GLint viewport[4]; 
GLfloat winX, winY, winZ; 
glGetDoublev(GL_MODELVIEW_MATRIX, modelViewMatrix); 
glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix); 
glGetIntegerv(GL_VIEWPORT, viewport); 

winX = (float)x; 
winY = (float)viewport[3] - (float)y; 
glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ); 

GLdouble nearPlaneLocation[3]; 
gluUnProject(winX, winY, 0, modelViewMatrix, projectionMatrix, 
      viewport, &nearPlaneLocation[0], &nearPlaneLocation[1], 
     &nearPlaneLocation[2]); 

GLdouble farPlaneLocation[3]; 
gluUnProject(winX, winY, 1, modelViewMatrix, projectionMatrix, 
      viewport, &farPlaneLocation[0], &farPlaneLocation[1], 
     &farPlaneLocation[2]); 

QVector3D nearP = QVector3D(nearPlaneLocation[0], nearPlaneLocation[1], 
      nearPlaneLocation[2]); 
QVector3D farP = QVector3D(farPlaneLocation[0], farPlaneLocation[1], 
      farPlaneLocation[2]); 

我覺得我使用衝突的系統或其他東西。

我應該使用不同的變量來管理我的相機嗎?我看到投影視圖,模型視圖等的討論,但我不明白我將如何使用它,並使用着色器程序。當談到OpenGL時,我仍然是新手。

所以澄清:我試圖將我的鼠標座標轉換成三維空間座標。到目前爲止,它似乎是半工作,它只是沒有考慮到相機旋轉。我確認我的問題與射線創建有關,或者與座標的未投影有關,與我的實際射線拾取邏輯無關。

+0

只要你知道,在窗口空間的近平面是** ** 0.0和遠平面** ** 1.0。您正在使用'z'的錯誤座標。實際上,除非你有一點恰好在近剪​​裁平面上,否則它可能並不重要。 – 2015-02-10 00:43:40

+0

哎呀,忘了改回來。在提交它之前,我一直在瘋狂地改變價值觀以解決問題,我會改變這一點。 – Yattabyte 2015-02-10 01:11:24

+0

另外,我不認爲簡單否定窗口系統鼠標座標是正確的。你想從頂部到底部改變原點,所以它通常是'maxY - Y'。 – 2015-02-10 01:38:10

回答

1

在這裏,我想我有一系列的問題。

  1. 我應該用-1我近平面,而不是0
  2. 我已經不同了我的矩陣數據類型(QT的人而言,),使我不能直接將它們插入unproject功能。

我解決了這些通過執行以下操作:

  1. 我安裝了GLM library規範化我的數據類型
  2. 我進行矩陣計算自己
    • 所以我把矩陣轉換成我的然後將逆視矩陣乘以逆矩陣矩陣,然後乘以逆投影矩陣。
    • 然後將該值乘以屏幕座標的2個不同向量(必須在NDC空間中)。一個z爲-1,另一個+1對應於窗口空間的近平面和遠平面。最後,這些矢量也必須具有1的「w」值,以便由此產生的矩陣*矢量的計算可以除以它自己的最後一個點。

我有一個系列的,因爲我的射線的初始問題採摘導致我的代碼揭示了一系列的錯誤在這裏開幕的問題。 如果有人遇到張貼在這裏的問題,它可能是值得一試我,我開了其他問題,從投影問題,我所有的問題都幹:

  • In here,我才知道,其實我需要一些爲了創建光線而進行的計算形式。
  • In here,我得知unProject沒有工作,因爲我試圖使用OpenGL函數來拉模型和查看矩陣,但是我從來沒有真正將它們設置在第一位,因爲我手動構建了矩陣。我解決了這個問題2次:我手動完成了數學計算,並且製作了所有相同數據類型的矩陣(它們是早期的混合數據類型,也導致了問題)。我知道我的操作順序稍微偏離了(需要將矩陣乘以一個矢量,而不是相反),我的近平面需要爲-1,而不是0,並且矢量的最後一個值這將乘以矩陣(值「w」)需要爲1.

由於我的問題延長了相當長的時間,並拿出了幾個問題,我欠相信幾個人誰幫助我前進的道路:

2

它看起來很像你被混合不同的功能組/級別絆倒。你有一些使用固定功能矩陣堆棧的方面。例如,在您的繪圖功能:

glMatrixMode(GL_MODELVIEW); 
glLoadIdentity();  
gluLookAt(cameraPosition.x(), cameraPosition.y(), cameraPosition.z(), camX, camY, 0, cameraUpDirection.x(), cameraUpDirection.y(), cameraUpDirection.z()); 

或者在未投影功能:

glGetDoublev(GL_MODELVIEW_MATRIX, modelViewMatrix); 
glGetDoublev(GL_PROJECTION_MATRIX, projectionMatrix); 

但在其他地方,你構建自己的矩陣,並將它們傳遞到着色器制服:

vMatrix.lookAt(cameraPosition, QVector3D(camX, camY, 0), cameraUpDirection); 
... 
shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix); 

這些是實現相同功能的兩種不同方式。但是你不能自由地混合和匹配它們的片段。如果你想保持乾淨和可預測的東西,你應該選擇一個,並堅持下去。由於第一個功能已過時,我建議您堅持構建自己的矩陣,並使用着色器代碼中定義的制服。

舉個例子來說明爲什麼你當前的特徵組合是令人失望的祕訣:你從固定函數矩陣堆棧中獲得當前投影矩陣與glGetDoublev(GL_PROJECTION_MATRIX, ...)。但至少在此處顯示的代碼中,您從未使用矩陣堆棧指定投影矩陣。所以這只是給你的身份矩陣。就OpenGL而言,作爲統一着色器程序的pMatrix矩陣完全不相關。

重寫你的整個代碼將是這個答案有點多,所以這裏只是指針的關鍵部分:

  • 擺脫指矩陣堆棧的所有呼叫。這包括調用glMatrixMode(),glLoadIdentity(),gluLookAt()glGetDoublev()調用來獲取當前矩陣。
  • 對所有渲染使用着色器(如果您還未使用),並在GLSL代碼中將所有需要的矩陣定義爲制服。
  • 自己計算和管理矩陣,可以使用自己的代碼,也可以是廣泛使用的矩陣/矢量庫之一。
  • 將這些矩陣作爲制服傳遞給着色器。

現在,對於未投影,它看起來像你已經擁有你的模型,視圖和投影矩陣(pMatrixvMatrixmMatrix)。因此,不需要任何glGet*()調用來從OpenGL中檢索它們。將vMatrixmMatrix相乘得到modelViewMatrix,並直接使用pMatrix作爲您傳遞給gluUnProject()的投影矩陣。

嚴格地說,我也會考慮GLU棄用。但如果你仍然很喜歡使用gluUnProject(),那麼現在可能是最簡單的。否則,常用的矩陣庫可能會實現它。或者,如果您不害怕弄髒手,如果您查看一些說明基本計算的規格/文檔,應該不難實現。