OpenGL: 填充非凸多边形 (转)

OpenGL多边形填充时默认为凸多边形
[cpp]  view plain copy
  1. void display()  
  2. {  
  3.     glClear(GL_COLOR_BUFFER_BIT);  
  4.     glColor3f(1.0, 1.0, 1.0);  
  5.     glBegin(GL_POLYGON);  
  6.     {  
  7.         glVertex2i(380, 380);  
  8.         glVertex2i(320, 410);  
  9.         glVertex2i(180, 280);  
  10.         glVertex2i(90, 330);  
  11.         glVertex2i(50, 310);  
  12.         glVertex2i(50, 150);  
  13.         glVertex2i(90, 130);  
  14.         glVertex2i(180, 180);  
  15.         glVertex2i(320, 50);  
  16.         glVertex2i(380, 80);  
  17.     }  
  18.     glEnd();  
  19.     glLineWidth(2.0);  
  20.     glColor3f(1.0, 0.0, 0.0);  
  21.     glBegin(GL_LINE_LOOP);  
  22.     {  
  23.         glVertex2i(380, 380);  
  24.         glVertex2i(320, 410);  
  25.         glVertex2i(180, 280);  
  26.         glVertex2i(90, 330);  
  27.         glVertex2i(50, 310);  
  28.         glVertex2i(50, 150);  
  29.         glVertex2i(90, 130);  
  30.         glVertex2i(180, 180);  
  31.         glVertex2i(320, 50);  
  32.         glVertex2i(380, 80);  
  33.     }  
  34.     glEnd();  
  35.     glFlush();  
  36. }  
填充结果:

OpenGL: 填充非凸多边形 (转)_第1张图片

       OpenGL中认为合法的多边形必须是凸多边形,凹多边形、自交多边形、带孔的多边形等非凸的多边形在OpenGL中绘制会出现出乎意料的结果。例如,在大多数系统中,只有多边形的凸包被填充,而在有些系统中,并非所有的凸包都被填充。OpenGL之所以对合法多边形类型做出限制,是为了更方便地提供能够对符合条件的多边形进行快速渲染的硬件。简单多边形可被快速地渲染,而复杂多边形难以快速检测出来。为了最大限度的提高性能,OpenGL假定多边形是简单的。

OpenGL: 填充非凸多边形 (转)_第2张图片

      非凸多边形最简单的填充方法最简单的应该是GLU 网格化对象GLUtesselator

就是GLUtesselator, 能将任意多边形,简化为三角形或凸多边形的组合,从而使OpenGL能绘制出任意形状的多边形。

1. gluNewTess();                 //创建一个新的分格化对象
2. gluTessCallback();            //注册回调函数,完成分格化的一些操作,照着写就行了。
3. gluTessProperty();            //可有可无的,设置一些分格化的属性值
4. gluTessBeginPolygon();        //开始画多边形
    draw polygon...              //在这里画多边形,一个一个点画就可以,最后一个点会和第一个点自动连接起来
    gluTessEdnPolygon();         //结束画多边形
5. gluDeleteTess();              //删除分格化对象
[cpp]  view plain copy
  1. #include   
  2. #include   
  3. #include   
  4.   
  5. #pragma comment(lib,"glut32.lib")  
  6.   
  7. GLdouble quad[12][3] = {   
  8.     {-2,3,0},   {-2,0,0},   {2,0,0},    { 2,3,0},  
  9.     {-1,2,0},   {-1,1,0},   {1,1,0},    { 1,2,0},  
  10.     {-0.5,1,0}, {-0.5,2,0}, {0.5,2,0}, { 0.5,1,0} };   
  11.   
  12. void myIdle(void)   
  13. {  
  14.     glutPostRedisplay();  
  15. }  
  16. //------------------------------------------------------------  OnDraw()  
  17. //  
  18. void CALLBACK vertexCallback(GLvoid *vertex)  
  19. {  
  20.     const GLdouble *pointer = (GLdouble *) vertex;  
  21.     glColor3dv(pointer + 3);//在此设置颜色  
  22.     glVertex3dv(pointer);  
  23. }  
  24. void CALLBACK beginCallback(GLenum which)  
  25. {  
  26.     glBegin(which);  
  27. }  
  28. void CALLBACK endCallback  ()  
  29. {  
  30.     glEnd();  
  31. }  
  32. void CALLBACK errorCallback(GLenum errorCode)  
  33. {  
  34.     const GLubyte *estring;  
  35.     estring = gluErrorString(errorCode);  
  36.     fprintf(stderr, "Tessellation Error: %s\n", estring);  
  37.     exit(0);  
  38. }  
  39. void CALLBACK combineCallback(GLdouble coords[3],  
  40.                               GLdouble *vertex_data[4],  
  41.                               GLfloat weight[4], GLdouble **dataOut )  
  42. {  
  43.     GLdouble *vertex;  
  44.     int i;  
  45.     vertex = (GLdouble *) malloc(6 * sizeof(GLdouble));  
  46.     vertex[0] = coords[0];  
  47.     vertex[1] = coords[1];  
  48.     vertex[2] = coords[2];  
  49.     for (i = 3; i < 7; i++)  
  50.     {  
  51.         vertex[i] = weight[0] * vertex_data[0][i]  
  52.             + weight[1] * vertex_data[1][i]  
  53.             + weight[2] * vertex_data[2][i]  
  54.             + weight[3] * vertex_data[3][i];  
  55.     }  
  56.     *dataOut = vertex;  
  57. }   
  58. void OnDraw()   
  59. {  
  60.     // clear the screen & depth buffer  
  61.     glClear(GL_COLOR_BUFFER_BIT);  
  62.   
  63.     // clear the previous transform  
  64.     glLoadIdentity();  
  65.   
  66.     GLUtesselator *tobj = gluNewTess();  
  67.     if (!tobj) {    return;     }  
  68.   
  69.     gluTessCallback(tobj, GLU_TESS_VERTEX, (void (CALLBACK *)())vertexCallback);  
  70.     gluTessCallback(tobj, GLU_TESS_BEGIN, (void (CALLBACK *)())beginCallback);  
  71.     gluTessCallback(tobj, GLU_TESS_END, (void (CALLBACK *)())endCallback);  
  72.     gluTessCallback(tobj, GLU_TESS_ERROR, (void (CALLBACK *)())errorCallback);  
  73.     gluTessCallback(tobj, GLU_TESS_COMBINE, (void (CALLBACK *)())combineCallback);  
  74.   
  75.     // glShadeModel(GL_FLAT);  
  76.   
  77.     // gluTessProperty(tobj,GLU_TESS_WINDING_RULE,GLU_TESS_WINDING_POSITIVE); //GLU_TESS_WINDING_ODD  
  78.   
  79.     gluTessBeginPolygon(tobj, NULL);  
  80.   
  81.     gluTessBeginContour(tobj);  
  82.     gluTessVertex(tobj, quad[0], quad[0]);  
  83.     gluTessVertex(tobj, quad[1], quad[1]);  
  84.     gluTessVertex(tobj, quad[2], quad[2]);  
  85.     gluTessVertex(tobj, quad[3], quad[3]);  
  86.     gluTessEndContour(tobj);  
  87.   
  88.     gluTessBeginContour(tobj);                      // inner quad (hole)  
  89.     gluTessVertex(tobj, quad[4], quad[4]);  
  90.     gluTessVertex(tobj, quad[5], quad[5]);  
  91.     gluTessVertex(tobj, quad[6], quad[6]);  
  92.     gluTessVertex(tobj, quad[7], quad[7]);  
  93.     gluTessEndContour(tobj);  
  94.   
  95.     gluTessBeginContour(tobj);                      // inner quad (hole)  
  96.     gluTessVertex(tobj, quad[8], quad[8]);  
  97.     gluTessVertex(tobj, quad[9], quad[9]);  
  98.     gluTessVertex(tobj, quad[10], quad[10]);  
  99.     gluTessVertex(tobj, quad[11], quad[11]);  
  100.     gluTessEndContour(tobj);  
  101.   
  102.     gluTessEndPolygon(tobj);  
  103.   
  104.     gluDeleteTess(tobj);   
  105.     glutSwapBuffers();  
  106. }  
  107. //------------------------------------------------------------  OnInit()  
  108. //  
  109. void OnInit()   
  110. {  
  111.     //glClearColor(1,1,1,0);  
  112. }  
  113. //------------------------------------------------------------  OnExit()  
  114. //  
  115. void OnExit()   
  116. {  
  117. }  
  118. //------------------------------------------------------------  OnReshape()  
  119. //  
  120. void OnReshape(int w, int h)  
  121. {  
  122.     // prevents division by zero when minimising window  
  123.     if (h == 0)  
  124.     {   h = 1;  }  
  125.   
  126.     // set the drawable region of the window  
  127.     glViewport(0, 0, w, h);  
  128.   
  129.     // set up the projection matrix  
  130.     glMatrixMode(GL_PROJECTION);  
  131.     glLoadIdentity();  
  132.   
  133.     // just use a perspective projection  
  134.     //gluPerspective(45,(float)w/h,0.1,100);  
  135.     if(w <= h)  
  136.     {  
  137.         glOrtho(-4.0, 4.0, -4.0 * (GLfloat)h / (GLfloat)w, 4.0 * (GLfloat)h / (GLfloat)w, 0.0, 100.0);  
  138.     }  
  139.     else  
  140.     {  
  141.         glOrtho(-4.0, 4.0, -4.0 * (GLfloat)h / (GLfloat)w, 4.0 * (GLfloat)h / (GLfloat)w, 0.0, 100.0);  
  142.     }  
  143.   
  144.     // go back to model view matrix so we can move the objects about  
  145.     glMatrixMode(GL_MODELVIEW);  
  146.     glLoadIdentity();  
  147. }  
  148. //------------------------------------------------------------  main()  
  149. //  
  150. int main(int argc,char** argv)  
  151. {  
  152.     // initialize glut  
  153.     glutInit(&argc,argv);  
  154.     // request a depth buffer, RGBA display mode, and we want double buffering  
  155.     glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);  
  156.     // set the initial window size  
  157.     glutInitWindowSize(480, 480);  
  158.     // create the window  
  159.     glutCreateWindow("filling");  
  160.     // run our custom initialisation  
  161.     OnInit();  
  162.     // set the function to use to draw our scene  
  163.     glutDisplayFunc(OnDraw);  
  164.     // set the function to handle changes in screen size  
  165.     glutReshapeFunc(OnReshape);  
  166.     //  glutIdleFunc(&myIdle);  
  167.     // set the function to be called when we exit  
  168.     atexit(OnExit);  
  169.   
  170.     // this function runs a while loop to keep the program running.  
  171.     glutMainLoop();  
  172.   
  173.     return 0;  
  174. }  
简单版:
[cpp]  view plain copy
  1. #include   
  2. #include   
  3. #include   
  4.   
  5. #pragma comment(lib,"glut32.lib")  
  6.   
  7. GLdouble quad[12][3] =   
  8. {   
  9.     {5,5,0},    {15,5,0},   {15,-5,0},  { 5,-5,0},  
  10.     {0,5,0},    {-15,10,0}, {-5,-10,0}, { -10,5,0},  
  11.     {-0.5,1,0}, {-0.5,2,0}, {0.5,2,0},  { 0.5,1,0}   
  12. };   
  13. void myIdle(void)   
  14. {  
  15.     glutPostRedisplay();  
  16. }  
  17.   
  18. //------------------------------------------------------------  OnDraw()  
  19. //  
  20. void CALLBACK PolyLine3DBegin(GLenum type)  
  21. {  
  22.     glBegin(type);  
  23. }  
  24.   
  25. void CALLBACK PolyLine3DVertex ( GLdouble * vertex)  
  26. {  
  27.     const GLdouble *pointer = (GLdouble *) vertex;  
  28.     glColor3d(1.0,0,0);//在此设置颜色  
  29.     glVertex3dv(pointer);  
  30. }  
  31.   
  32. void CALLBACK PolyLine3DEnd()  
  33. {  
  34.     glEnd();  
  35. }  
  36. GLUtesselator* tesser()  
  37. {  
  38.     GLUtesselator * tess;  
  39.     tess=gluNewTess();  
  40.     gluTessCallback(tess,GLU_TESS_BEGIN,(void (CALLBACK*)())&PolyLine3DBegin);   
  41.     gluTessCallback(tess,GLU_TESS_VERTEX,(void (CALLBACK*)())&PolyLine3DVertex);   
  42.     gluTessCallback(tess,GLU_TESS_END,(void (CALLBACK*)())&PolyLine3DEnd);  
  43.     return tess;  
  44. }  
  45.   
  46. /////////////////////////////////////////////////////////////////////////////////  
  47. void OnDraw()  
  48. {  
  49.   
  50.     glClear(GL_STENCIL_BUFFER_BIT);  
  51.   
  52.     GLUtesselator* tess = tesser();  
  53.     if (!tess) return;  
  54.     gluTessBeginPolygon(tess,NULL);  
  55.   
  56.     gluTessBeginContour(tess);  
  57.     for(int i = 0; i < 4; i++)  
  58.     {  
  59.         gluTessVertex(tess, quad[i], quad[i]);  
  60.     }  
  61.     gluTessEndContour(tess);  
  62.   
  63.     gluTessBeginContour(tess);  
  64.     for(int i = 4; i < 8;i++)  
  65.     {  
  66.         gluTessVertex(tess, quad[i], quad[i]);  
  67.     }  
  68.     gluTessEndContour(tess);  
  69.   
  70.     gluTessEndPolygon(tess);  
  71.     glutSwapBuffers();  
  72. }  
  73. //------------------------------------------------------------  OnInit()  
  74. //  
  75. void OnInit()   
  76. {  
  77.     //glClearColor(1,1,1,0);  
  78. }  
  79.   
  80. //------------------------------------------------------------  OnExit()  
  81. //  
  82. void OnExit()  
  83. {  
  84. }  
  85. //------------------------------------------------------------  OnReshape()  
  86. //  
  87. void OnReshape(int w, int h)  
  88. {  
  89.     // prevents division by zero when minimising window  
  90.     if (h == 0)  
  91.     {  
  92.         h = 1;  
  93.     }  
  94.     // set the drawable region of the window  
  95.     glViewport(0, 0, w, h);  
  96.   
  97.     // set up the projection matrix  
  98.     glMatrixMode(GL_PROJECTION);  
  99.     glLoadIdentity();  
  100.   
  101.     // just use a perspective projection  
  102.     //gluPerspective(45,(float)w/h,0.1,100);  
  103.     if(w<=h)  
  104.     {  
  105.         glOrtho(-20.0, 20.0, -20.0 * (GLfloat)h / (GLfloat)w, 20.0 * (GLfloat)h / (GLfloat)w, 0.0, 100.0);  
  106.     }  
  107.     else  
  108.     {  
  109.         glOrtho(-20.0, 20.0, -20.0 * (GLfloat)h / (GLfloat)w, 20.0 * (GLfloat)h / (GLfloat)w, 0.0, 100.0);  
  110.     }  
  111.     // go back to model view matrix so we can move the objects about  
  112.     glMatrixMode(GL_MODELVIEW);  
  113.     glLoadIdentity();  
  114. }  
  115. //------------------------------------------------------------  main()  
  116. //  
  117. int main(int argc, char** argv)  
  118. {  
  119.   
  120.     // initialize glut  
  121.     glutInit(&argc, argv);  
  122.     // request a depth buffer, RGBA display mode, and we want double buffering  
  123.     glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);  
  124.     // set the initial window size  
  125.     glutInitWindowSize(480, 480);  
  126.     // create the window  
  127.     glutCreateWindow("fill tess");  
  128.     // run our custom initialization  
  129.     OnInit();  
  130.     // set the function to use to draw our scene  
  131.     glutDisplayFunc(OnDraw);  
  132.     // set the function to handle changes in screen size  
  133.     glutReshapeFunc(OnReshape);  
  134.     //  glutIdleFunc(&myIdle);  
  135.     // set the function to be called when we exit  
  136.     atexit(OnExit);  
  137.     // this function runs a while loop to keep the program running.  
  138.     glutMainLoop();  
  139.   
  140.     return 0;  
  141. }  
OpenGL: 填充非凸多边形 (转)_第3张图片



Reference:

其他填充方法:

http://www.cnblogs.com/mazhenyu/archive/2010/05/18/1738487.html

函数简介:

http://hi.baidu.com/zhujianzhai/item/6ed52336d67e7b9ab80c03eb

http://bbs.csdn.net/topics/100086684

各种填充算法详细讲解:

http://blog.csdn.net/orbit/article/details/7368996

http://blog.csdn.net/yangtrees/article/details/9040257


转自:http://blog.csdn.net/augusdi/article/details/20032185

你可能感兴趣的:(OpenGL: 填充非凸多边形 (转))