螢幕座標向OpenGL座標轉換

2021-08-25 19:10:30 字數 2464 閱讀 7568

很多人用opengl繪圖會遇到乙個問題即螢幕座標向opengl座標轉換,在網上流傳著如下類似的**:

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座標轉換

很多人用opengl繪圖會遇到乙個問題即螢幕座標向opengl座標轉換,在網上流傳著如下類似的 glint viewport 4 gldouble modelview 16 gldouble projection 16 glfloat winx,winy,winz gldouble posx,pos...

OpenGL 螢幕座標向OpenGL座標轉換

螢幕座標向opengl座標轉換 很多人用opengl繪圖會遇到乙個問題即螢幕座標向opengl座標轉換,在網上流傳著如下類似的 glint viewport 4 gldouble modelview 16 gldouble projection 16 glfloat winx,winy,winz g...

螢幕座標向opengl三維座標轉換

很多人用opengl繪圖會遇到乙個問題即螢幕座標向opengl座標轉換,在網上流傳著如下類似的 glint viewport 4 gldouble modelview 16 gldouble projection 16 glfloat winx,winy,winz gldouble posx,pos...