MFC+OpenGL 螢幕座標轉OpenGL座標
阿新 • • 發佈:2018-11-10
最近在寫一個例子用到了OpenGL,OpenGL的中心點(0, 0)點剛好是我們螢幕的中心點。因為我是需要動態的作圖(畫點、線、圓、弧...)需要平移 縮放圖形,所以我在座標轉換這個問題上卡住了。
滑鼠點選螢幕上的一點可以很方便的獲得通過OnLButtonDown(),但是把取到的螢幕點轉到OpenGL對應點卻需要做相應的計算。用到的核心函式是gluUnProject(),如下:
glPushMatrix(); //與之相對應的glPopMatrix()也一定不能少 //這裡的變換需要和繪圖時一致,否則座標會產生錯誤 glScalef(...); //縮放 glRotatef(...); //旋轉 glTranslatef(...); //平移 glGetIntegerv( GL_VIEWPORT,viewport ); //得到的是最後一個設定視口的引數 glGetDoublev( GL_MODELVIEW_MATRIX, modelview ); glGetDoublev( GL_PROJECTION_MATRIX, projection ); glPopMatrix(); winX = (float)point.x; winY = (float)viewport[3] - (float)point.y; glReadPixels(point.x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ ); gluUnProject(winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
從螢幕座標向OpenGL座標轉換需要經過兩步:第一步是螢幕座標向視景體座標轉換,第二步是視景體座標向OpenGL座標轉換。上述程式碼中winX = (float)point.x; winY = (float)viewport[3] - (float)point.y;反映第一步,gluUnProject()是第二步。一般說來,gluUnProject()的轉換是不會出問題的。
想要不出現問題就必須:
1. 在glGetIntegerv()之前必須添上模型變換的程式碼,即和繪圖時使用的模型變換程式碼一樣;
2. 必須保證平移、縮放、旋轉的順序和繪圖時的一致;另外,螢幕座標向視景體座標轉換要正確;
3. 在多視口情況下,活動視口必須最後繪製,使它作為當前的視口,這樣才能保證glGetIntegerv()等取值函式能夠得到正確的值;
以下是我繪圖時的程式碼,注意各種變換的順序要和左邊轉換時一致
glPushMatrix(); glLoadIdentity(); glScalef(...); glRotatef(...); glTranslatef(...); //兩條座標軸 glBegin(GL_LINES ); glColor3f(0.5f,1.0f,1.0f); glVertex2f(ptStartX, ptStartY); glVertex2f(ptEndX, ptEndY); glEnd(); glPopMatrix();