一、基本定義
世界窗口:在世界坐標系中定義一個對齊的矩形(aligned rectangle,即矩陣的邊與坐標軸平行)的窗口,這個世界窗口外的部分被裁減並不被繪制。OpenGL會自動地做剪裁。
視口:在顯示器的屏幕窗口上定義一個對齊的矩形的視口,OpenGL會自動建立世界窗口和視口的變換(包括縮放和平移)。當世界窗口中所有對象都被繪制時,對象在世界窗
口中的部分會被自動地映射到視口中————換句話說,被映射到屏幕坐標中,即像素在顯示器上的坐標。
二、相關函數介紹
1.對於二維繪圖來說,世界窗口由函數gluOrtho2D()設定,它的原型是:
void gluOrtho2D(GLDouble left,GLdouble right,GLdouble buttom,GLdouble top);
對於三維的情況,有另外兩個參數需要設定,后續講述。
2.視口的設定通過glViewport()函數,它的原型是:
void glViewport(GLint x,GLint y,GLint width,GLint ehignt);//它設置窗口的左下角,以及寬度和高度。
注意:因為openGL通過矩陣來完成所有的變換,因此GluOrtho2D()的調用必須在glMatrixModel(GL_PROJECTION)和glLoadIdentity()這兩個函數之后。
3.將設定窗口的部分放到setWindow()函數中,增加程序的可讀性:
void setWindow(GLdouble left,GLdouble right,GLdouble buttom,GLdouble top) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(left,right,bottom,top); //eg: gluOrtho2D(0.0,640.0,0.0,480.0); } //為了讓setViewport()更容易使用,我們將其參數作了輕微的調整使得它和setWindow()相匹配; //它們都是按左、右、下、上的順序做參數 void setViewport(GLint left,GLint right,GLint bottom,GLint top) { //right-left 等於寬度,top-bottom 等於高度 glViewport(left,bottom,right-left,top-bottom); }
三、應用樣例——平鋪
setWindow(0,640.0,0,440.0); for(int i = 0;i < 5;i++) { for(int j = 0;j < 5;j++) { glViewport(i * 64,j * 44,64,44); drawPolylineFile("dino.dat"); //dino.dat為存儲繪圖數據的文件,drawPolylineFile為畫該文件數據的函數 } }
四、程序示例
從文件中讀取數據繪制小房子,更改setWindow和setViewport的參數改變房子的大小
dot.dat
5 5 0 0 0 0 20 10 25 20 20 20 0 4 1 11 0 11 12 16 12 16 0 4 1 20 0 30 0 30 10 20 10 4 1 24 0 24 5 27 5 27 0 2 1 30 10 20 16
程序
#include "stdafx.h" #include <gl\glut.h> #include <fstream> using namespace std; const int screenWidth = 640; const int screenHeight = 480; void myInit(){ glClearColor(1.0, 1.0, 1.0, 0.0); glColor3f(0.0f, 0.0f, 0.0f); glPointSize(2.0); //glMatrixMode(GL_PROJECTION); //glLoadIdentity(); //gluOrtho2D(0.0, (GLdouble)screenWidth, 0.0, (GLdouble)screenHeight); } void setWindow(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(left, right, bottom, top); //eg: gluOrtho2D(0.0,640.0,0.0,480.0); } void setViewport(GLint left, GLint right, GLint bottom, GLint top) { //right-left 等於寬度,top-bottom 等於高度 glViewport(left, bottom, right - left, top - bottom); } void myDisplay(){ fstream inStream; char filename[] = "dot.dat"; inStream.open(filename, ios::in); if (inStream.fail()){ printf("Fail!!!!!\n"); return; } glClear(GL_COLOR_BUFFER_BIT); GLint numpolys, numLines, way, x, y; inStream >> numpolys; for (int j = 0; j < numpolys; j++) { inStream >> numLines; inStream >> way; if (way == 0){ glBegin(GL_LINE_LOOP); for (int i = 0; i < numLines; i++) { inStream >> x >> y; glVertex2i(x, y); } glEnd(); } else{ glBegin(GL_LINE_STRIP); for (int i = 0; i < numLines; i++) { inStream >> x >> y; glVertex2i(x, y); } glEnd(); } } glFlush(); inStream.close(); } int main(int argc, char **argv){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(screenWidth, screenHeight); glutInitWindowPosition(100, 150); glutCreateWindow("Dot Plot of a Function"); setWindow(0.0, 40.0, 0.0, 40.0); setViewport(0.0, 40.0, 0.0, 40.0); glutDisplayFunc(myDisplay); myInit(); glutMainLoop(); }
運行效果:
setWindow(0.0, 40.0, 0.0, 40.0);
setViewport(0.0, 40.0, 0.0, 40.0);

setWindow(0.0, 400.0, 0.0, 240.0);
setViewport(0.0, 400.0, 0.0, 240.0);

