日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

屏幕坐標(biāo)向OpenGL坐標(biāo)的轉(zhuǎn)換(完整版)

 賢人好客 2011-01-01
很多人用OpenGL繪圖會(huì)遇到一個(gè)問(wèn)題即屏幕坐標(biāo)向OpenGL坐標(biāo)轉(zhuǎn)換,在網(wǎng)上流傳著如下類似的代碼:

 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)是屏幕坐標(biāo),(winX, winY, winZ)是視景體坐標(biāo)及深度坐標(biāo),(posX, posY, posZ是OpenGL坐標(biāo)。

    上述代碼并不保險(xiǎn),只針對(duì)一種特殊情況才好使,即glViewport(0, 0, screenWidth, screenHeight),screenWidth、screenHeight分別是客戶區(qū)的寬和高,視口左下角坐標(biāo)恰好是(0,0),并且未經(jīng)過(guò)任何模型變換。

    從屏幕坐標(biāo)向OpenGL坐標(biāo)要經(jīng)過(guò)兩步,第一步是屏幕坐標(biāo)向視景體坐標(biāo)轉(zhuǎn)換,第二步是視景體坐標(biāo)向OpenGL坐標(biāo)轉(zhuǎn)換。上述代碼中winX = (float)x;  winY = viewport[3] - (float)y;反映第一步,gluUnProject是第二步。一般說(shuō)來(lái),gluUnProject的轉(zhuǎn)換是不會(huì)出問(wèn)題的。

    如何進(jìn)行正確的轉(zhuǎn)換呢?首先,在glGetIntegerv之前添上模型變換的代碼,和繪圖時(shí)使用的模型變換代碼一樣,另外必須保證平移,縮放,旋轉(zhuǎn)的順序和繪圖時(shí)的一樣。其次,屏幕坐標(biāo)向視景體坐標(biāo)轉(zhuǎn)換有兩種方式(注意!在多視口情況下,活動(dòng)視應(yīng)當(dāng)最后繪制,它將作為當(dāng)前的視口,保證glGetIntegerv等取值函數(shù)能得到正確的值)。①winx = x – viewport[0]; winy = screenHeight – viewport[1] - y; viewport[0] = viewport[1] = 0;②winx = x; winy = screenHeight – y;第一種比較直觀,前兩句是將屏幕坐標(biāo)轉(zhuǎn)換為視景體內(nèi)的坐標(biāo),后兩句將視景體的左下角點(diǎn)坐標(biāo)改為(0,0),因?yàn)樵谠O(shè)置裁剪視口時(shí),使用glViewport設(shè)置視口的左下角點(diǎn)坐標(biāo)不一定是(0,0),而在視景體內(nèi)的點(diǎn)其視景體坐標(biāo)與左下角點(diǎn)是相對(duì)的,即把視景體坐標(biāo)看作是坐標(biāo)系原點(diǎn)。第二種方式比較簡(jiǎn)略,但是同樣的道理,只不過(guò)是glUnproject函數(shù)對(duì)winx和winy又做了一次轉(zhuǎn)換。

    好了,現(xiàn)在給出完整的代碼,如下:

 GLint    viewport[4];
 GLdouble modelview[16];
 GLdouble projection[16];
 GLfloat  winX, winY, winZ;
 GLdouble posX, posY, posZ;

 glPushMatrix();
 
 // 變換要繪圖函數(shù)里的順序一樣,否則坐標(biāo)轉(zhuǎn)換會(huì)產(chǎn)生錯(cuò)誤
 glScalef(m_srtMatrix[0], m_srtMatrix[1], m_srtMatrix[2]); // 縮放、平移、旋轉(zhuǎn)變換
 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); // 得到的是最后一個(gè)設(shè)置視口的參數(shù)
 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); 
 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多