glint viewport[4];
gldouble modelview[16];
gldouble projection[16];
glfloat winx, winy, winz;
gldouble posx, posy, posz;
glgetintegerv(gl_viewport, viewport);
glgetdoublev(gl_modelview_matrix, modelview);
glgetdoublev(gl_projection_matrix, projection);
winx = (float)x;
winy = viewport[3] - (float)y;
glreadpixels((int)winx, (int)winy, 1, 1, gl_depth_component, gl_float, &winz);
gluunproject(winx, winy, winz, modelview, projection, viewport, &posx, &posy, &posz);
注:(x, y)是螢幕座標,(winx, winy, winz)是視景體座標及深度座標,(posx, posy, posz是opengl座標。
上述**並不保險,只針對一種特殊情況才好使,即glviewport(0, 0, screenwidth, screenheight),screenwidth、screenheight分別是客戶區的寬和高,視口左下角座標恰好是(0,0),並且未經過任何模型變換。
從螢幕座標向opengl座標要經過兩步,第一步是螢幕座標向視景體座標轉換,第二步是視景體座標向opengl座標轉換。上述**中winx = (float)x; winy = viewport[3] - (float)y;反映第一步,gluunproject是第二步。一般說來,gluunproject的轉換是不會出問題的。
如何進行正確的轉換呢?首先,在glgetintegerv之前添上模型變換的**,和繪圖時使用的模型變換**一樣,另外必須保證平移,縮放,旋轉的順序和繪圖時的一樣。其次,螢幕座標向視景體座標轉換有兩種方式(注意!在多視口情況下,活動視應當最後繪製,它將作為當前的視口,保證glgetintegerv等取值函式能得到正確的值)。①winx = x – viewport[0]; winy = screenheight – viewport[1] - y; viewport[0] = viewport[1] = 0;②winx = x; winy = screenheight – y;第一種比較直觀,前兩句是將螢幕座標轉換為視景體內的座標,後兩句將視景體的左下角點座標改為(0,0),因為在設定裁剪視口時,使用glviewport設定視口的左下角點座標不一定是(0,0),而在視景體內的點其視景體座標與左下角點是相對的,即把視景體座標看作是座標系原點。第二種方式比較簡略,但是同樣的道理,只不過是glunproject函式對winx和winy又做了一次轉換。
好了,現在給出完整的**,如下:
glint viewport[4];
gldouble modelview[16];
gldouble projection[16];
glfloat winx, winy, winz;
gldouble posx, posy, posz;
glpushmatrix();
// 變換要繪圖函式裡的順序一樣,否則座標轉換會產生錯誤
glscalef(m_srtmatrix[0], m_srtmatrix[1], m_srtmatrix[2]); // 縮放、平移、旋轉變換
glrotatef(m_srtmatrix[3], 1.0f, 0.0f, 0.0f);
glrotatef(m_srtmatrix[4], 0.0f, 1.0f, 0.0f);
glrotatef(m_srtmatrix[5], 0.0f, 0.0f, 1.0f);
gltranslatef(m_srtmatrix[6], m_srtmatrix[7], m_srtmatrix[8]);
glgetintegerv(gl_viewport, viewport); // 得到的是最後乙個設定視口的引數
glgetdoublev(gl_modelview_matrix, modelview);
glgetdoublev(gl_projection_matrix, projection);
glpopmatrix();
winx = x;
winy = screenheight - y;
glreadpixels((int)winx, (int)winy, 1, 1, gl_depth_component, gl_float, &winz);
gluunproject(winx, winy, winz, modelview, projection, viewport, &posx, &posy, &posz);
OpenGL 螢幕座標到物體三維座標的轉換
直接看 吧,有注釋。入參 int x,int y 表示螢幕的座標 glint viewport 4 gldouble modelview 16 gldouble projection 16 glfloat winx 0.0f glfloat winy 0.0f glfloat winz 0.0f g...
OpenGL 座標轉換
在opengl繪圖過程中,需要通過座標轉換將模型座標點的座標轉換為世界座標。如圖,要把模型座標系o x y z 中的點a座標轉換為世界座標oxyz的點座標,需要得到本地座標到世界座標的轉換矩陣。如圖,模型座標系中原點在世界座標系的座標是 2,2,2 點a在模型座標中的座標是 3,2,1 根據模型座標...
OpenGL座標轉換總結
前面整理過乙個,不過後來感覺不是很對,這裡重新寫一下。先解釋一下這個問題,在opengl程式設計中,經常會需要與使用者的互動,比如對檢視進行指定點旋轉,獲取模型座標點等。而這些操作最方便的就是通過滑鼠進行操作,但滑鼠只能獲得螢幕座標,那麼如何轉換到opengl世界座標就成了乙個亟待解決的問題。一 理...