2017-02-15 102 views
1

我嘗試在GLM函數glm :: unProject上實現光線拾取方法。我在屏幕上錯誤的光線位置和錯誤的視角的問題。下面的一些簡單的代碼...glm :: unProject不起作用,屏幕上的光線位置不正確

我的注視功能:

glm::mat4 ViewMatrix() 
{ 
    Front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch)); 
    Front.y = -sin(glm::radians(Pitch)); 
    Front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch)); 
    Right = glm::normalize(glm::cross(Front, WorldUp)); 
    Up = glm::normalize(glm::cross(Right, Front)); 
    glm::vec3 PositionPan = RightPan + UpPan; 
    Position += PositionPan; 

    return glm::lookAt((Position + radius * (Front)), Position , Up); 
} 

你會發現我的功能包括錯誤的參數,但我想打免費攝像頭(類似於3ds Max和等)針對0,0,0可能的平移(PositionPan for Position)和縮放(radius)。我花了很多時間來正確地工作,而且我不知道有什麼其他方式可以讓它成爲另一種方式。我懷疑這些功能是否與GLM的Ray功能錯誤工作有關。如果您發現有問題,請告訴我。

我的變換函數:

glm::mat4 view = ViewMatrix(); 
glm::mat4 projection = glm::perspective(1.0f, 
(float)screenWidth/(float)screenHeight, 0.1f, 100.0f); 

我的雷功能:

void Ray(posx, posy, glm::mat4 view, glm::mat4 projection) 
{ 
    x = (posx/screenWidth - 0.5f) * 2.0f; 
    y = (posy/screenHeight - 0.5f) * -2.0f; 

    worldSpaceNear = glm::unProject(glm::vec3(x, y, 0.0), 
    view, projection,   
    glm::vec4(0.0, 0.0, screenWidth, screenHeight)); 

    worldSpaceFar = glm::unProject(glm::vec3(x, y, 1.0), 
    view, projection, 
    glm::vec4(0.0, 0.0, screenWidth, screenHeight)); 
} 

接着我通過在VAO worldSpaceNear /遠參數和產生在幾何着色器的一長的平行六面從近開始到遠飛機。從屏幕空間轉換到剪輯空間是正確的,但在調試時,光線從左下角開始並立即消失。鼠標在屏幕上的位置對射線影響不大。 但是! 如果我改變了雷功能,經典的方法:

void mRay(glm::mat4 view, glm::mat4 projection 
{ 
    x = (posx/screenWidth - 0.5f) * 2.0f; 
    y = (posy/screenHeight - 0.5f) * -2.0f; 

    glm::vec4 localNear{ x, y, 0.0, 1.0 }; 
    glm::vec4 localFar{ x, y, 1.0, 1.0 }; 

    auto wsn = glm::inverse(projection * view) * localNear; 
    worldSpaceNear = glm::vec3(wsn.x, wsn.y, wsn.z); 

    auto wsf = glm::inverse(projection * view) * localFar; 
    worldSpaceFar = glm::vec3(wsf.x, wsf.y, wsf.z); 

}

一切幾乎是確定。雷跟進一個鼠標,但它有一個不正確的觀點。射線必須按照視角分散,但在我的情況下,它渴望到遠平面的中心。我該如何解決這個問題,或者我該如何在GLM上解決它?

更新DERHASS

mRay()後,我送worldSpaceNear /遠渲染循環。 我KHOW ussually工作與方向,但我這樣做:

renderLine(glm::vec3 worldSpaceNear, glm::vec3 worldSpaceFar, 
glm::mat4 view, glm::mat4 projection, glm::vec3 colorOverlay, 
Shader shader) 
{ 
... 
//Create VAO, VBO 
... 
GLfloat vertices[] ={ 
    worldSpaceNear.x - 0.01, worldSpaceNear.y + 0.01, worldSpaceNear.z, 
    worldSpaceFar.x - 0.01, worldSpaceFar.y + 0.01, worldSpaceFar.z, 
    worldSpaceNear.x - 0.01, worldSpaceNear.y - 0.01, worldSpaceNear.z... 
// Long box from near to far 
... 
glDrawArrays(GL_LINE_LOOP, 0, 8); 
} 

在頂點着色器只是:

gl_Position = projection * view * model * vec4(position, 1.0f); 

現在,我想可能是我忘了從視圖矩陣除去旋轉部件的線,反之亦然,以增加相機的旋轉。

回答

1

glm::unProject窗口sapce取消投射一個點到眼睛空間(或任何您插入的矩陣)。但是,你沒有投射的點是

x = (posx/screenWidth - 0.5f) * 2.0f; 
y = (posy/screenHeight - 0.5f) * -2.0f; 

這不是窗口空間。您實際上將其轉換爲標準化的設備座標。 unproject函數將在內部進行轉換(這就是爲什麼您需要傳遞四個視口參數)。這也解釋了爲什麼光線沒有太大的移動,因爲當把這些值解釋爲窗口空間時,在整個屏幕上移動鼠標只會將它改變兩個像素。

你必須自己做的唯一事情是y中的鏡像,作爲GL的窗口空間的原點是在左下:

x = posx; 
y = screenHeight - 1.0f - posy; 
+0

謝謝!我用GLM unproject和鼠標座標正確顯示解決了這個問題。但是我的光芒變成了鼠標下的一個點。你在LookAt部件中發現了一些奇怪的東西嗎? – OpenGLNoob

+0

我不認爲你的「LookAt」電話是怪罪。但是如果您正在使用創建射線的相關代碼,則不會顯示全部內容。 – derhass

+0

derhass Look update! – OpenGLNoob