您的位置:首页 > 运维架构

OpenGL填充非凸多边形(网格化)

2015-12-25 20:12 1106 查看
OpenGL多边形填充时默认为凸多边形

[cpp] view
plaincopy





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假定多边形是简单的。





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

就是GLUtesselator, 能将任意多边形,简化为三角形或凸多边形的组合,从而使OpenGL能绘制出任意形状的多边形。
1. gluNewTess(); //创建一个新的分格化对象

2. gluTessCallback(); //注册回调函数,完成分格化的一些操作,照着写就行了。

3. gluTessProperty(); //可有可无的,设置一些分格化的属性值

4. gluTessBeginPolygon(); //开始画多边形

draw polygon... //在这里画多边形,一个一个点画就可以,最后一个点会和第一个点自动连接起来

gluTessEdnPolygon(); //结束画多边形

5. gluDeleteTess(); //删除分格化对象

[cpp] view
plaincopy





#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;

}

简单版:

[cpp] view
plaincopy





#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 /article/1623025.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: