OpenGL: 多边形分格化 和 gluTessCallback() 函数在c++中的使用方法

虽然在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);
}

void IntersectionInfoCache::makePolygonDrawData(std::vector<GeoLocation>& vecPoints, std::vector<uint16>& triangleIndexList, uint8 drawelement, //多边形描画数据 vector<IntersectionImageData>& imageData) { std::vector<PolygonTessVertex> points; uint32 pointcount = vecPoints.size(); points.reserve(pointcount); for(int32 i = 0;i < pointcount;++i) { PolygonTessVertex m_point; m_point.vertex.x = vecPoints[i].longitude; m_point.vertex.y = vecPoints[i].latitude; points.emplace_back(m_point); } TessPolygon(points, triangleIndexList); std::vector<GeoLocation> vecTessPoints; uint32 pointcountTess = points.size(); vecTessPoints.reserve(pointcountTess); for(int32 i = 0;i < pointcountTess;++i) { GeoLocation m_point; m_point.longitude = points[i].vertex.x; m_point.latitude = points[i].vertex.y; vecTessPoints.emplace_back(m_point); } IntersectionImageData tempimagedata; tempimagedata.drawelement = drawelement; tempimagedata.vertex.assign(vecTessPoints.begin(), vecTessPoints.end()); tempimagedata.index.assign(triangleIndexList.begin(), triangleIndexList.end()); imageData.emplace_back(tempimagedata); } void TessPolygon(std::vector<PolygonTessVertex> &points, std::vector<uint16> &triangleIndexList) { auto uiPointCount = points.size(); GLUtesselator* tobj = gluNewTess(); gluTessCallback(tobj, GLU_TESS_VERTEX_DATA, (_GLUfuncptr)PolygonVertexCallback); gluTessCallback(tobj, GLU_TESS_BEGIN_DATA, (_GLUfuncptr)PolygonBeginCallback); gluTessCallback(tobj, GLU_TESS_END_DATA, (_GLUfuncptr)PolygonEndCallback); gluTessCallback(tobj, GLU_TESS_ERROR_DATA, (_GLUfuncptr)PolygonErrorCallback); gluTessCallback(tobj, GLU_TESS_COMBINE_DATA, (_GLUfuncptr)PolygonCombineCallback); gluTessProperty(tobj, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); PolygonData_t stPolygonData; gluTessBeginPolygon(tobj, &stPolygonData); gluTessBeginContour(tobj); /* for loop statement: the initial value of decltype(uiPointCount) Index is 0 / for(decltype(uiPointCount) Index = 0; Index < uiPointCount; ++Index) { stPolygonData.vecVertexArray.emplace_back(points[Index]); TessPolygonVertex tempTessVertex; tempTessVertex.location[0] = points[Index].vertex.x; tempTessVertex.location[1] = points[Index].vertex.y; gluTessNormal(tobj, 0.0, 0.0, 1.0); gluTessVertex(tobj, tempTessVertex.location, (GLvoid)Index); } gluTessEndContour(tobj); gluTessEndPolygon(tobj); gluDeleteTess(tobj); points.swap(stPolygonData.vecVertexArray); triangleIndexList.swap(stPolygonData.vecDrawIndices); }加上注释
06-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值