2016-07-18 68 views
0

我嘗試使用碰撞進行射線拾取,這意味着屏幕上的2D位置會轉換爲模型空間中的3D位置。 我的問題是,射線並不總是與模型相交以產生有效的3D位置。通過glm :: unproject將2D邊緣切換到3D模型空間 - 射線不與模型相交

這是我做的:

我的幀緩衝,從它創建深度紋理glReadPixels()後。

glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, screenWidth, screenHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); 

cv::Mat_<float> depthCV(screenHeight, screenWidth); 
glReadPixels(0, 0, screenWidth, screenHeight, GL_DEPTH_COMPONENT, GL_FLOAT, depthCV.ptr()); 

我後來線性化的深度,並通過cv::Canny()存儲到一個cv::Mat_<uchar>的邊緣檢測:(不要忘了翻轉圖像)

cv::blur(gray, edge, cv::Size(3, 3)); 
cv::Canny(edge, edge, edgeThresh, edgeThresh * ratio, 3); 

...並獲得通過輪廓

0:

cv::findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE, cv::Point(0, 0)); 

二維座標輪廓(一個或多個)的(X,Y)現在正在3D模型轉化通過座標

GLint viewport[4]; 
GLfloat winX, winY, winZ; 
glGetIntegerv(GL_VIEWPORT, viewport); 
winX = (float)x; 
winY = (float)viewport[3] - (float)(y); 
glReadPixels(x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ); 
glm::vec4 viewportvec(viewport[0], viewport[1], viewport[2], viewport[3]); 
glm::vec3 winCoords(winX, winY, winZ); 

glm::vec3 modelCoords = glm::unProject(winCoords, view*model, proj, viewportvec); 

做完這些之後,看着它顯示的3D點,有些光線不與模型相交。射線的長度接近遠平面的值。 我試圖通過查看輸入(x,y)周圍的一個像素鄰域來擴大輸入。還有一些光線不與模型相交。

任何想法,爲什麼這是?或者如何解決它?先前模糊的邊緣提取是否對它負責?

Teapot

我附其中分佈可以看到的圖像。藍色點是與模型不相交的點(射線的長度接近遠平面的值),紅點是。我使用茶壺模型進行測試。

我不想在這裏粘貼我的整個代碼以方便閱讀。如果需要更多的代碼或信息來更好地瞭解可能的錯誤,請告訴我。

回答

0

邊緣提取與以前的模糊負責嗎?

是的,當然。

我建議您不要使用邊緣檢測後處理過濾器,而要使用邊緣提取柵格化片段着色器。它實際上很簡單:

將臉部法線變換爲屏幕座標(每個片段)。如果abs(screenspace_normal.z) < threshold臉部垂直於屏幕,因此是一個邊緣。對於不是邊緣discard片段的所有片段。剩下的是(接近)邊緣並可以進一步處理的片段。

請注意,這也會提取「隱藏」表面的邊緣。所以你可能應該執行一個「早期的Z」傳遞來進行深度測試,然後第二次傳遞不會寫入深度緩衝區並且只發出邊緣碎片。