OpenGL 填充非凸多边形

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                OpenGL多边形填充时默认为凸多边形
void display(){ glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glBegin(GL_POLYGON); {  glVertex2i(380, 380);  glVertex2i(320, 410);  glVertex2i(180, 280);  glVertex2i(90, 330);  glVertex2i(50, 310);  glVertex2i(50, 150);  glVertex2i(90, 130);  glVertex2i(180, 180);  glVertex2i(320, 50);  glVertex2i(380, 80); } glEnd(); glLineWidth(2.0); glColor3f(1.0, 0.0, 0.0); glBegin(GL_LINE_LOOP); {  glVertex2i(380, 380);  glVertex2i(320, 410);  glVertex2i(180, 280);  glVertex2i(90, 330);  glVertex2i(50, 310);  glVertex2i(50, 150);  glVertex2i(90, 130);  glVertex2i(180, 180);  glVertex2i(320, 50);  glVertex2i(380, 80); } glEnd(); glFlush();}
填充结果:


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

polygon

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

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

扫描二维码关注公众号,回复: 4103321 查看本文章
1. gluNewTess();                 //创建一个新的分格化对象
2. gluTessCallback();            //注册回调函数,完成分格化的一些操作,照着写就行了。
3. gluTessProperty();            //可有可无的,设置一些分格化的属性值
4. gluTessBeginPolygon();        //开始画多边形
    draw polygon...              //在这里画多边形,一个一个点画就可以,最后一个点会和第一个点自动连接起来
    gluTessEdnPolygon();         //结束画多边形
5. gluDeleteTess();              //删除分格化对象
#include <stdio.h>#include <stdlib.h>#include <GL/glut.h>#pragma comment(lib,"glut32.lib")GLdouble quad[12][3] = {  {-2,3,0}, {-2,0,0}, {2,0,0}, { 2,3,0}, {-1,2,0}, {-1,1,0}, {1,1,0}, { 1,2,0}, {-0.5,1,0}, {-0.5,2,0}, {0.5,2,0}, { 0.5,1,0} }; void myIdle(void) { glutPostRedisplay();}//------------------------------------------------------------ OnDraw()//void CALLBACK vertexCallback(GLvoid *vertex)const GLdouble *pointer = (GLdouble *) vertex; glColor3dv(pointer + 3);//在此设置颜色 glVertex3dv(pointer);}void CALLBACK beginCallback(GLenum which){ glBegin(which);}void CALLBACK endCallback  (){ glEnd();}void CALLBACK errorCallback(GLenum errorCode)const GLubyte *estring; estring = gluErrorString(errorCode); fprintf(stderr, "Tessellation Error: %s\n", estring); exit(0);}void CALLBACK combineCallback(GLdouble coords[3],         GLdouble *vertex_data[4],         GLfloat weight[4], GLdouble **dataOut ){ GLdouble *vertex; int i; vertex = (GLdouble *) malloc(6 * sizeof(GLdouble)); vertex[0] = coords[0]; vertex[1] = coords[1]; vertex[2] = coords[2]; for (i = 3; i < 7; i++) {  vertex[i] = weight[0] * vertex_data[0][i]   + weight[1] * vertex_data[1][i]   + weight[2] * vertex_data[2][i]   + weight[3] * vertex_data[3][i]; } *dataOut = vertex;} void OnDraw() // clear the screen & depth buffer glClear(GL_COLOR_BUFFER_BIT); // clear the previous transform glLoadIdentity(); GLUtesselator *tobj = gluNewTess(); if (!tobj) { return;  } gluTessCallback(tobj, GLU_TESS_VERTEX, (void (CALLBACK *)())vertexCallback); gluTessCallback(tobj, GLU_TESS_BEGIN, (void (CALLBACK *)())beginCallback); gluTessCallback(tobj, GLU_TESS_END, (void (CALLBACK *)())endCallback); gluTessCallback(tobj, GLU_TESS_ERROR, (void (CALLBACK *)())errorCallback); gluTessCallback(tobj, GLU_TESS_COMBINE, (void (CALLBACK *)())combineCallback); // glShadeModel(GL_FLAT); // gluTessProperty(tobj,GLU_TESS_WINDING_RULE,GLU_TESS_WINDING_POSITIVE); //GLU_TESS_WINDING_ODD gluTessBeginPolygon(tobj, NULL); gluTessBeginContour(tobj); gluTessVertex(tobj, quad[0], quad[0]); gluTessVertex(tobj, quad[1], quad[1]); gluTessVertex(tobj, quad[2], quad[2]); gluTessVertex(tobj, quad[3], quad[3]); gluTessEndContour(tobj); gluTessBeginContour(tobj);                      // inner quad (hole) gluTessVertex(tobj, quad[4], quad[4]); gluTessVertex(tobj, quad[5], quad[5]); gluTessVertex(tobj, quad[6], quad[6]); gluTessVertex(tobj, quad[7], quad[7]); gluTessEndContour(tobj); gluTessBeginContour(tobj);                      // inner quad (hole) gluTessVertex(tobj, quad[8], quad[8]); gluTessVertex(tobj, quad[9], quad[9]); gluTessVertex(tobj, quad[10], quad[10]); gluTessVertex(tobj, quad[11], quad[11]); gluTessEndContour(tobj); gluTessEndPolygon(tobj); gluDeleteTess(tobj);  glutSwapBuffers();}//------------------------------------------------------------ OnInit()//void OnInit() //glClearColor(1,1,1,0);}//------------------------------------------------------------ OnExit()//void OnExit() {}//------------------------------------------------------------ OnReshape()//void OnReshape(int w, int h)// prevents division by zero when minimising window if (h == 0) { h = 1; } // set the drawable region of the window glViewport(0, 0, w, h); // set up the projection matrix glMatrixMode(GL_PROJECTION); glLoadIdentity(); // just use a perspective projection //gluPerspective(45,(float)w/h,0.1,100); if(w <= h) {  glOrtho(-4.0, 4.0, -4.0 * (GLfloat)h / (GLfloat)w, 4.0 * (GLfloat)h / (GLfloat)w, 0.0, 100.0); } else {  glOrtho(-4.0, 4.0, -4.0 * (GLfloat)h / (GLfloat)w, 4.0 * (GLfloat)h / (GLfloat)w, 0.0, 100.0); } // go back to model view matrix so we can move the objects about glMatrixMode(GL_MODELVIEW); glLoadIdentity();}//------------------------------------------------------------ main()//int main(int argc,char** argv)// initialize glut glutInit(&argc,argv); // request a depth buffer, RGBA display mode, and we want double buffering glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); // set the initial window size glutInitWindowSize(480, 480); // create the window glutCreateWindow("filling"); // run our custom initialisation OnInit(); // set the function to use to draw our scene glutDisplayFunc(OnDraw); // set the function to handle changes in screen size glutReshapeFunc(OnReshape); // glutIdleFunc(&myIdle); // set the function to be called when we exit atexit(OnExit); // this function runs a while loop to keep the program running. glutMainLoop(); return 0;}
简单版:
#include <stdio.h>#include <stdlib.h>#include <GL/glut.h>#pragma comment(lib,"glut32.lib")GLdouble quad[12][3] = {  {5,5,0}, {15,5,0}, {15,-5,0}, { 5,-5,0}, {0,5,0}, {-15,10,0}, {-5,-10,0}, { -10,5,0}, {-0.5,1,0}, {-0.5,2,0}, {0.5,2,0}, { 0.5,1,0} }; void myIdle(void) { glutPostRedisplay();}//------------------------------------------------------------ OnDraw()//void CALLBACK PolyLine3DBegin(GLenum type){ glBegin(type);}void CALLBACK PolyLine3DVertex ( GLdouble * vertex)const GLdouble *pointer = (GLdouble *) vertex; glColor3d(1.0,0,0);//在此设置颜色 glVertex3dv(pointer);}void CALLBACK PolyLine3DEnd(){ glEnd();}GLUtesselator* tesser(){ GLUtesselator * tess; tess=gluNewTess(); gluTessCallback(tess,GLU_TESS_BEGIN,(void (CALLBACK*)())&PolyLine3DBegin);  gluTessCallback(tess,GLU_TESS_VERTEX,(void (CALLBACK*)())&PolyLine3DVertex);  gluTessCallback(tess,GLU_TESS_END,(void (CALLBACK*)())&PolyLine3DEnd); return tess;}/////////////////////////////////////////////////////////////////////////////////void OnDraw(){ glClear(GL_STENCIL_BUFFER_BIT); GLUtesselator* tess = tesser(); if (!tess) return; gluTessBeginPolygon(tess,NULL); gluTessBeginContour(tess); for(int i = 0; i < 4; i++) {  gluTessVertex(tess, quad[i], quad[i]); } gluTessEndContour(tess); gluTessBeginContour(tess); for(int i = 4; i < 8;i++) {  gluTessVertex(tess, quad[i], quad[i]); } gluTessEndContour(tess); gluTessEndPolygon(tess); glutSwapBuffers();}//------------------------------------------------------------ OnInit()//void OnInit() //glClearColor(1,1,1,0);}//------------------------------------------------------------ OnExit()//void OnExit(){}//------------------------------------------------------------ OnReshape()//void OnReshape(int w, int h)// prevents division by zero when minimising window if (h == 0) {  h = 1; } // set the drawable region of the window glViewport(0, 0, w, h); // set up the projection matrix glMatrixMode(GL_PROJECTION); glLoadIdentity(); // just use a perspective projection //gluPerspective(45,(float)w/h,0.1,100); if(w<=h) {  glOrtho(-20.0, 20.0, -20.0 * (GLfloat)h / (GLfloat)w, 20.0 * (GLfloat)h / (GLfloat)w, 0.0, 100.0); } else {  glOrtho(-20.0, 20.0, -20.0 * (GLfloat)h / (GLfloat)w, 20.0 * (GLfloat)h / (GLfloat)w, 0.0, 100.0); } // go back to model view matrix so we can move the objects about glMatrixMode(GL_MODELVIEW); glLoadIdentity();}//------------------------------------------------------------ main()//int main(int argc, char** argv)// initialize glut glutInit(&argc, argv); // request a depth buffer, RGBA display mode, and we want double buffering glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); // set the initial window size glutInitWindowSize(480, 480); // create the window glutCreateWindow("fill tess"); // run our custom initialization OnInit(); // set the function to use to draw our scene glutDisplayFunc(OnDraw); // set the function to handle changes in screen size glutReshapeFunc(OnReshape); // glutIdleFunc(&myIdle); // set the function to be called when we exit atexit(OnExit); // this function runs a while loop to keep the program running. glutMainLoop(); return 0;}



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
           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述

猜你喜欢

转载自blog.csdn.net/ytffhew/article/details/84076838