Opengl分格化(libtess)移植与使用
http://blog.csdn.net/wind_hzx/article/details/11830425简介:
Opengl只能直接显示简单的凸多边形,对于凹的多边形则只能通过分格化(tessellation)将其分格成多个小的凸多边形,以便于利用opengl的标准渲染函数对其进行渲染。对于正常使用的话,直接使用glut库中则含有了分格化的相关API。但是对于如果使用gles等其他方式,不能使用或者不想使用glut的时候,则无法直接使用glut库的(可能导致opengl上下文冲突等),所以需要重新编译源码,只取其中的分格化相关的API。
移植编译libtess:
在网上查找libtess,下载其源码。比如:http://glues.googlecode.com/svn/trunk/glues/source/libtess在glues.h头文件中加入你自己当前的opengl头文件,比如我当前的为gles2.0:
- #elif defined(_WIN32) && (defined(_M_IX86) || defined(_M_X64))
- /* mainly for PowerVR OpenGL ES 1.x win32 emulator */
- #include <GLES2/gl2.h>
- #undef APIENTRY
- #define APIENTRY
- #define GLAPI
对于上述编译后的libtess,用法则与glut中的使用方式一样了,但是我们发现:
1. 当分格化后的顶点数据需要存储起来一次性绘制,而不是以前的直接调用glBegin,glVertex的时候。
2. 由于分格化会采用效率优先的方式,可能的顶点组织方式为GL_TRIANGLE_FAN、GL_TRIANGLE_STRIP等方式,无法统一绘制。
所以基于以上问题,我们对源码进行修改,设定只按照GL_TRIANGLES的方式来进行顶点的组织。
在render.c文件中:
- static void RenderMaximumFaceGroup(GLUtesselator* tess, GLUface* fOrig)
- {
- GLUhalfEdge* e=fOrig->anEdge;
- struct FaceCount max, newFace;
- max.size=1;
- max.eStart=e;
- max.render=&RenderTriangle;
- /*
- if (!tess->flagBoundary)
- {
- newFace=MaximumFan(e );
- if (newFace.size>max.size)
- {
- max=newFace;
- }
- newFace=MaximumFan(e->Lnext);
- if (newFace.size>max.size)
- {
- max=newFace;
- }
- newFace=MaximumFan(e->Lprev);
- if (newFace.size>max.size)
- {
- max=newFace;
- }
- newFace=MaximumStrip(e);
- if (newFace.size>max.size)
- {
- max=newFace;
- }
- newFace=MaximumStrip(e->Lnext);
- if (newFace.size>max.size)
- {
- max=newFace;
- }
- newFace=MaximumStrip(e->Lprev);
- if (newFace.size>max.size)
- {
- max=newFace;
- }
- }
- */
- (*(max.render))(tess, max.eStart, max.size);
- }
使用方式:
glut正常使用方式:
- #include <glut.h>
- GLdouble rect[4][3] = {
- 0, 0, 0,
- 1, 0, 0,
- 1, 1, 0,
- 0, 1, 0
- };
- GLdouble tri[3][3] =
- {
- 0.25, 0.25, 0,
- 0.75, 0.25, 0,
- 0.5, 0.5, 0
- };
- GLUtesselator* tobj;
- void vertexBack(void* vertex_data)
- {
- GLdouble* vertex = (GLdouble*)vertex_data;
- GLdouble x = vertex[0];
- GLdouble y = vertex[1];
- GLdouble z = vertex[2];
- glVertex3dv(vertex);
- }
- void tessBegin(GLenum type)
- {
- glBegin(type);
- }
- void tessEnd()
- {
- glEnd();
- }
- void drawTess()
- {
- gluTessBeginPolygon(tobj, 0);
- gluTessBeginContour(tobj);
- gluTessVertex(tobj, rect[0], rect[0]);
- gluTessVertex(tobj, rect[1], rect[1]);
- gluTessVertex(tobj, rect[2], rect[2]);
- gluTessVertex(tobj, rect[3], rect[3]);
- gluTessEndContour(tobj);
- gluTessBeginContour(tobj);
- gluTessVertex(tobj, tri[0], tri[0]);
- gluTessVertex(tobj, tri[1], tri[1]);
- gluTessVertex(tobj, tri[2], tri[2]);
- gluTessEndContour(tobj);
- gluTessEndPolygon(tobj);
- }
- void createTess()
- {
- tobj = gluNewTess();
- gluTessCallback(tobj, GLU_TESS_BEGIN, (void (__stdcall *)())glBegin);
- gluTessCallback(tobj, GLU_TESS_END, (void (__stdcall *)())glEnd);
- gluTessCallback(tobj, GLU_TESS_VERTEX, (void (__stdcall *)())glVertex3dv);
- }
- void func()
- {
- glClear(GL_COLOR_BUFFER_BIT);
- glColor3f(1, 0, 0);
- drawTess();
- glFlush();
- }
- void reshape(int w, int h)
- {
- glViewport(0, 0, w, h);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluOrtho2D(-w/2, w/2, -h/2, h/2);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- }
- int main(int argc, char** argv)
- {
- glutInit(&argc, argv);
- glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
- glutInitWindowPosition(110, 110);
- glutInitWindowSize(400, 400);
- glutCreateWindow("test");
- createTess();
- glutDisplayFunc(func);
- glutReshapeFunc(reshape);
- glutMainLoop();
- return 0;
- }