虽然在OpenGL中可以使用glBegin(GL_POLYGON)来画一个多边形,但是它只能实现简单的凸多边形。对于一些复杂的多边形,比如凹多边形,或者有实心有空心的多边形,OpenGL的glBegin(GL_POLYGON)就不能满足需求了。
通常可以采用一种叫做"分格化"的方法来画复杂的多边形。要用分格化的方法画多边形,步骤如下:
1. gluNewTess(); //创建一个新的分格化对象
2. gluTessCallback(); //注册回调函数,完成分格化的一些操作,照着写就行了。
3. gluTessProperty(); //可有可无的,设置一些分格化的属性值
4. gluTessBeginPolygon(); //开始画多边形
draw polygon...//在这里画多边形,一个一个点画就可以,最后一个点会和第一个点自动连接起来
gluTessEdnPolygon(); //结束画多边形
5. gluDeleteTess(); //删除分格化对象
在后面会附上一段分格化的代码,虽然很简单,但是按照书上的给的例子在c++中编程,gluTessCallback()函数会报错。它的函数原型是:
void gluTessCallback(GLUtesselator * tessobj, GLenum type, void(*fn)());
在C语言中使用gluTessCallback()是可以像下面这样写的。
gluTessCallback(tobj, GLU_TESS_VERTEX, glVertex3dv);
gluTessCallback(tobj, GLU_TESS_BEGIN, beginCallback);
gluTessCallback(tobj, GLU_TESS_END, endCallback);
gluTessCallback(tobj, GLU_TESS_ERROR, errorCallback);
但是换到c++里面,就会出现下面的错误。
error C2664: 'gluTessCallback' : cannot convert parameter 3 from 'void (__stdcall *)(const GLdouble *)' to 'void (__stdcall *)(void)'
None of the functions with this name in scope match the target type
error C2664: 'gluTessCallback' : cannot convert parameter 3 from 'void (__stdcall *)(GLenum)' to 'void (__stdcall *)(void)'
None of the functions with this name in scope match the target type
error C2664: 'gluTessCallback' : cannot convert parameter 3 from 'void (__stdcall *)(GLenum)' to 'void (__stdcall *)(void)'
None of the functions with this name in scope match the target type
其实主要原因是在进行强制类型转换的时候,在C++和C语言中是有区别的,所以c++就报错的。
解决方法如下:
gluTessCallback(tobj, GLU_TESS_VERTEX, (void (__stdcall *)())glVertex3dv);
gluTessCallback(tobj, GLU_TESS_BEGIN, (void (__stdcall *)())beginCallback);
gluTessCallback(tobj, GLU_TESS_END, (void (__stdcall *)())endCallback);
gluTessCallback(tobj, GLU_TESS_ERROR, (void (__stdcall *)())errorCallback);
分格化的一段代码:
在paint()中:
GLdouble rect[4][3] = { 50.0, 50.0, 0.0,
200.0, 50.0, 0.0,
200.0, 200.0, 0.0,
50.0, 200.0, 0.0};
GLUtesselator * tobj;
tobj = gluNewTess();
gluTessCallback(tobj, GLU_TESS_VERTEX, (void (__stdcall *)())glVertex3dv);
gluTessCallback(tobj, GLU_TESS_BEGIN, (void (__stdcall *)())beginCallback);
gluTessCallback(tobj, GLU_TESS_END, (void (__stdcall *)())endCallback);
gluTessCallback(tobj, GLU_TESS_ERROR, (void (__stdcall *)())errorCallback);
glShadeModel(GL_FLAT);
gluTessBeginPolygon(tobj, NULL);
gluTessBeginContour(tobj);
for(int i = 0; i < 4; i ++){
gluTessNormal(tobj, 0.0, 1.0, 0.0);
gluTessVertex(tobj, vertice[i], vertice[i]);
gluTessEndContour(tobj);
gluTessEndPolygon(tobj);
gluDeleteTess(tobj);
下面是回调函数:
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);
}