Opengl分格化(libtess)移植与使用

本文介绍如何使用OpenGL处理凹多边形的分片化,并提供了一个针对libtess库的修改方案,使其能够适应特定的应用场景,例如在 GLES 环境下使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介:

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);
}
如上所示,将其他的绘制方式都注掉,只按照GL_TRIANGLES方式进行生成。

使用方式:

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;
}
对于我们修改后的libtess,则不需要去判断回调后的绘制类型了,直接将全部的顶点保存起来,然后用于顶点缓冲区中绘制。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值