OpenGL没有办法直接绘制非凸多边形,但是可以通过gluTessVertex()这种OpenGL的“细分”的方法对非凸多边形进行绘制。具体原理是:
GLUtesselator, 能将任意多边形,简化为三角形或凸多边形的组合,从而使OpenGL能绘制出任意形状的多边形。
1. gluNewTess(); //创建一个新的分格化对象但是实际操作过程中一定要注意一个问题:
多变形上的点要保证在gluTessEndPolygon()执行之前空间不被释放,一般地,在开始gluTessBeginContour()之前多边形的点就应该已经指定了!!!
否则会出现绘制不出图像的现象,因为OpenGL没有读取到点的信息。以下是我在MFC框架View中用OpenGL绘制任意多边形的方法,大家有兴趣的可以看一下。
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(); } void DrawFloor(DataFloor* floor) { if (!floor) return; std::vector<glm::vec3>& boundary_pts = *floor->GetBoundaryPtsToFloor();//这里获取点的坐标 size_t amount_pts = boundary_pts.size(); if (amount_pts < 3) return; GLdouble(*quad)[3]; quad = new GLdouble[amount_pts][3];//申请动态内存 for (int i = 0; i < amount_pts; i++)//初始化所有的点到GLdouble(*quad)[3]中 { glm::vec3 pt = boundary_pts.at(i); quad[i][0] = pt.x; quad[i][1] = pt.y; quad[i][2] = pt.z; } GLfloat curColor[4]; glGetFloatv(GL_CURRENT_COLOR, curColor); glColor3ub((GLubyte)220, (GLubyte)220, (GLubyte)220); GLUtesselator* tess = gluNewTess(); if (!tess) return; gluTessCallback(tess, GLU_TESS_BEGIN, (void (CALLBACK*)())&PolyLine3DBegin); gluTessCallback(tess, GLU_TESS_VERTEX, (void (CALLBACK*)())&PolyLine3DVertex); gluTessCallback(tess, GLU_TESS_END, (void (CALLBACK*)())&PolyLine3DEnd); gluTessBeginPolygon(tess, NULL); gluTessBeginContour(tess); for (int i = 0; i< amount_pts; i++) {//绘制Tess“细分”出的点 gluTessVertex(tess, quad[i], quad[i]); } gluTessEndContour(tess); gluTessEndPolygon(tess); glColor3f(curColor[0], curColor[1], curColor[2]); delete[] quad;//释放内存 }
效果如下:
之前我有转载两篇关于“Tess”细分的原理以及细节解释的文章,有兴趣的朋友可以看一下。