计算机图形学杨武影像科学与技术实验室东南大学计算机学院yangwu@seu.edu.cn2第二章之第三节三维图形3主要内容提供一个更复杂的三维图形示例–分形:Sierpinski垫介绍隐藏面消除4三维图形应用程序在OpenGL中二维应用程序是三维应用程序的特殊情形对于3D图形应用程序–无需很大修改–使用glVertex3*()–必须考虑多边形绘制的顺序或者启用隐藏面消除功能–只考虑平面的简单凸多边形5SierpinskiGasket(2D)从一个三角形开始连接三边的中点并去掉中间的三角形重复上述过程6示例五次细分7分形考虑黑色填充区域的面积与周长(即包含填充区域的所有线段总长)当持续细分时–面积趋向于零–但周长趋向于无穷因此无穷细分后的结果不是通常的几何形状–既不是一维的,也不是二维的称之为分形(fractionaldimension)8程序开头#includeGL/glut.h/*apointdatatypetypedefGLfloatpoint2[2];/*initialtriangle*/point2v[]={{-1.0,-0.58},{1.0,-0.58},{0.0,1.15}};intn;//numberofrecursivesteps9绘制三角形voidtriangle(point2a,point2b,point2c)/*displayonetriangle*/{glBegin(GL_TRIANGLES);glVertex2fv(a);glVertex2fv(b);glVertex2fv(c);glEnd();}10三角形细分voiddivide_triangle(point2a,point2b,point2c,intm){/*trianglesubdivisionusingvertexnumbers*/point2v0,v1,v2;intj;if(m0){for(j=0;j2;j++)v0[j]=(a[j]+b[j])/2;for(j=0;j2;j++)v1[j]=(a[j]+c[j])/2;for(j=0;j2;j++)v2[j]=(b[j]+c[j])/2;divide_triangle(a,v0,v1,m-1);divide_triangle(c,v1,v2,m-1);divide_triangle(b,v2,v0,m-1);}else(triangle(a,b,c));/*drawtriangleatendofrecursion*/}11显示与初始化函数voiddisplay(void){glClear(GL_COLOR_BUFFER_BIT);divide_triangle(v[0],v[1],v[2],n);glFlush();}voidmyinit(){glMatrixMode(GL_PROJECTION);glLoadIdentity();gluOrtho2D(-2.0,2.0,-2.0,2.0);glMatrixMode(GL_MODELVIEW);glClearColor(1.0,1.0,1.0,1.0)glColor3f(0.0,0.0,0.0);}12Main()函数intmain(intargc,char**argv){n=4;glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowSize(500,500);glutCreateWindow(“2DGasket);glutDisplayFunc(display);myinit();glutMainLoop();return1;}13作业参考Sierpinski垫程序,选择一种分形,完成绘制–KochSnow–Julia集•Zn+1=Zn2+C–Mandelbrot集–…14改至3D通过下述修改,可以很容易地把程序生成三维图形:typedefGlfloatpoint3[3]glVertex3fglOrtho但这并没有多大实质性改变下面从四面体开始迭代153DGasket细分四面体的四个面16Example5次迭代后17三角形代码voidtriangle(pointa,pointb,pointc){glBegin(GL_POLYGON);glVertex3fv(a);glVertex3fv(b);glVertex3fv(c);glEnd();}18细分代码voiddivide_triangle(pointa,pointb,pointc,intm){pointv1,v2,v3;intj;if(m0){for(j=0;j3;j++)v1[j]=(a[j]+b[j])/2;for(j=0;j3;j++)v2[j]=(a[j]+c[j])/2;for(j=0;j3;j++)v3[j]=(b[j]+c[j])/2;divide_triangle(a,v1,v2,m-1);divide_triangle(c,v2,v3,m-1);divide_triangle(b,v3,v1,m-1);}else(triangle(a,b,c));}19生成四面体voidtetrahedron(intm){glColor3f(1.0,0.0,0.0);divide_triangle(v[0],v[1],v[2],m);glColor3f(0.0,1.0,0.0);divide_triangle(v[3],v[2],v[1],m);glColor3f(0.0,0.0,1.0);divide_triangle(v[0],v[3],v[1],m);glColor3f(0.0,0.0,0.0);divide_triangle(v[0],v[2],v[3],m);}20问题由于三角形是按照在程序中定义的顺序画出的,本来在前面的三角形并不是显示在位于它后面的三角形的前面getthiswantthis21隐藏面消除只想见到那些位于其它面前面的曲面或平面OpenGL采用称为z缓冲区的算法进行隐藏面消除,在z缓冲区中存贮着对象的深度信息,从而只有前面的对象出现在图像中22Z缓冲区算法在该算法中创建专门的缓冲区(称为z缓冲区),当几何体经过流水线各步骤时,存贮着该几何体的深度信息启用该算法的要素–在main()中•glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH)–在init()中•glEnable(GL_DEPTH_TEST)–在显示回调函数中•glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)