1、在这个矩形方位之外定义的图形,不能被显示出来。注意,当没有为应用程序指定裁剪窗口时,就使用默认的坐标:xWinMin-1.0, xWinMax1.0, yWinMin-1.0, yWinMax1.0。这样,默认的裁剪窗口是以坐标系原点为中心,边长为2的正方形区域。那么,这个范围内的图形,显示在显示器上生成窗口的哪个位置呢?这需要通过视区函数(ViewPort,有时也称视口)来指定:glViewport(xViewportMin, xViewportMax, viewportWidth, viewportHeight);这里的所有参数用对应于显示窗口的整数屏幕坐标给出,参数xViewportMi
2、n和yViewportMin指定视区左下角的位置,视区的宽度和高度用参数viewportWidth和viewportHeight指定。也就是说,用gluOrtho2D指定显示范围的图形在用glViewport指定的窗口位置显示出来。注意,当没有在应用程序中用glViewport指定视区时,则默认的视区大小及位置与整个OpenGL显示窗口一样。显然,当gluOrtho2D和glViewport指定的矩形区域的宽高比不一样时,图形会发生形变。那么,已经在世界坐标系中定义的物体,计算机的显示系统怎样确定哪些部分显示,哪些部分不显示呢?这是通过相关的裁减算法计算出来的。二、裁减算法1、点的裁剪判断点
3、P=(x, y)是否在裁剪区域( xWinMin, xWinMax, yWinMin, yWinMax )内,只要判断是否满足条件如果满足,就表明在裁剪区域内,否则,就在裁剪区域之外。2、线段的裁减线段的裁减要判断线段与裁剪矩形边界的各种关系。经典的线段裁剪算法有Cohen-Sutherland 算法和梁友栋-Barskey 算法。Cohen-Sutherland 算法的代码如下:class wcPt2D public: GLfloat x, y;inline GLint round (const GLfloat a) return GLint (a + 0.5); /* Define a f
4、our-bit code for each of the outside regions of a * rectangular clipping window. */const GLint winLeftBitCode = 0x1;const GLint winRightBitCode = 0x2;const GLint winBottomBitCode = 0x4;const GLint winTopBitCode = 0x8;/* A bit-mask region code is also assigned to each endpoint of an input * line segm
5、ent, according to its position relative to the four edges of * an input rectangular clip window. * * An endpoint with a region-code value of 0000 is inside the clipping * window, otherwise it is outside at least one clipping boundary. If * the or operation for the two endpoint codes produces a value
6、 of * false, the entire line defined by these two endpoints is saved * (accepted). If the and operation between two endpoint codes is * true, the line is completely outside the clipping window, and it is * eliminated (rejected) from further processing.inline GLint inside (GLint code) return GLint (!
7、code);inline GLint reject (GLint code1, GLint code2) return GLint (code1 & code2);inline GLint accept (GLint code1, GLint code2) return GLint (!(code1 | code2);GLubyte encode (wcPt2D pt, wcPt2D winMin, wcPt2D winMax) GLubyte code = 0x00; if (pt.x winMax.x) code = code | winRightBitCode; if (pt.y win
8、Max.y) code = code | winTopBitCode; return (code);void swapPts (wcPt2D * p1, wcPt2D * p2) wcPt2D tmp; tmp = *p1; *p1 = *p2; *p2 = tmp;void swapCodes (GLubyte * c1, GLubyte * c2) GLubyte tmp; tmp = *c1; *c1 = *c2; *c2 = tmp;void lineClipCohSuth (wcPt2D winMin, wcPt2D winMax, wcPt2D p1, wcPt2D p2) GLu
9、byte code1, code2; GLint done = false, plotLine = false; GLfloat m; while (!done) code1 = encode (p1, winMin, winMax); code2 = encode (p2, winMin, winMax); if (accept (code1, code2) done = true; plotLine = true; else if (reject (code1, code2) else /* Label the endpoint outside the display window as
10、p1. */ if (inside (code1) swapPts (&p1, &p2); swapCodes (&code1, &code2); /* Use slope m to find line-clipEdge intersection. */ if (p2.x != p1.x) m = (p2.y - p1.y) / (p2.x - p1.x); if (code1 & winLeftBitCode) p1.y += (winMin.x - p1.x) * m; p1.x = winMin.x; winRightBitCode) p1.y += (winMax.x - p1.x)
11、* m; p1.x = winMax.x; winBottomBitCode) /* Need to update p1.x for nonvertical lines only. */ p1.x += (winMin.y - p1.y) / m; p1.y = winMin.y; winTopBitCode) p1.x += (winMax.y - p1.y) / m; p1.y = winMax.y; if (plotLine) lineBres (round (p1.x), round (p1.y), round (p2.x), round (p2.y);/lineBres直线生成算法前
12、面添加以下的OpenGL glut的框架,并加上键盘控制,注意在把前面的Bresenham直线生成算法加到最前面:void myDisplay() wcPt2D winMin , winMax , p1 , p2; winMin.x=100; winMin.y=200;/定义裁剪窗口 winMax.x=400; winMax.y=400; p1.x=50; p1.y=50; /定义被裁剪的直线端点 p2.x=450; p2.y=450; glClear(GL_COLOR_BUFFER_BIT); glColor3f (1.0f, 0.0f, 0.0f); glRectf(winMin.x ,w
13、inMin.y ,winMax.x,winMax.y); /绘制红色裁剪矩形 glColor3f (1.0f, 1.0f, 1.0f); if (flag) lineClipCohSuth (winMin, winMax,p1,p2);/ 绘制裁剪线段 glBegin(GL_LINES); glVertex2i(p1.x,p1.y); glVertex2i(p2.x,p2.y); glEnd(); glFlush();void Init() glClearColor(0.0, 0.0, 0.0, 0.0); glMatrixMode (GL_PROJECTION); gluOrtho2D (0
14、.0, 640.0, 0.0, 480.0);void Reshape(int w, int h) glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h);void keyboard(unsigned char key, int x, int y) if (key=c | key=C) flag=true;rR) flag=false; glutPostRedisplay(
15、);int main(int argc, char *argv) glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowPosition(100, 100); glutInitWindowSize(640, 480); glutCreateWindow(Cohen-Sutherland直线裁减算法,C键裁减,R键复原); Init(); glutDisplayFunc(myDisplay); glutReshapeFunc(Reshape); glutKeyboardFunc(keyb
16、oard); glutMainLoop(); return 0;梁友栋-Barskey 算法的代码如下:class wcPt2D private: /* Default Constructor: initialize position as (0.0, 0.0). */ wcPt2D ( ) x = y = 0.0; void setCoords (GLfloat xCoord, GLfloat yCoord) x = xCoord; y = yCoord; GLfloat getx ( ) const return x; GLfloat gety ( ) const return y;GLi
17、nt clipTest (GLfloat p, GLfloat q, GLfloat * u1, GLfloat * u2) GLfloat r; GLint returnValue = true; if (p *u2) returnValue = false; else if (r *u1) *u1 = r; if (p r = q / p; if (r returnValue = false; else if (r *u2 = r; /* Thus p = 0 and line is parallel to clipping boundary. */ if (q 0.0) /* Line
18、is outside clipping boundary. */ return (returnValue);void lineClipLiangBarsk (wcPt2D winMin, wcPt2D winMax, wcPt2D p1, wcPt2D p2) GLfloat u1 = 0.0, u2 = 1.0, dx = p2.getx ( ) - p1.getx ( ), dy; if (clipTest (-dx, p1.getx ( ) - winMin.getx ( ), &u1, &u2) if (clipTest (dx, winMax.getx ( ) - p1.getx (
19、 ), &u2) dy = p2.gety ( ) - p1.gety ( ); if (clipTest (-dy, p1.gety ( ) - winMin.gety ( ), & if (clipTest (dy, winMax.gety ( ) - p1.gety ( ), & if (u2 p1.setCoords (p1.getx ( ) + u1 * dx, p1.gety ( ) + u1 * dy); lineBres (round (p1.getx ( ), round (p1.gety ( ), round (p2.getx ( ), round (p2.gety ( ); 再加上前面的框架代码,把其中的调用lineClipCohSuth改为lineClipLiangBarsk,注意参数的赋值。三、上机练习完整实现Cohen-Sutherland和梁友栋-Barskey线段裁减算法,理解裁减的基本原理,并继续体会怎样用键盘来控制图形的显示。
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1