http://www.glprogramming.com/red/chapter11.html
#include <GL/glut.h>
#include <malloc.h>
GLuint startList;
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glCallList(startList);
glCallList(startList + 1);
glFlush();
}
/*注册对应阶段回调函数*/
//开始绘制回调(类似glBegin())
void CALLBACK beginCallback(GLenum which)
{
glBegin(which);
}
//错误回调
void CALLBACK errorCallback(GLenum errorCode)
{
const GLubyte *estring;
estring = gluErrorString(errorCode);
}
//结束绘制回调(类似glEnd())
void CALLBACK endCallback(void)
{
glEnd();
}
//顶点数据回调
void CALLBACK vertexCallback(GLdouble *vertex)
{
const GLdouble *pointer;
pointer = (GLdouble *)vertex;
glColor3dv(pointer + 3);
glVertex3dv(vertex);
}
//相交处创建新顶点回调
void CALLBACK combineCallback(GLdouble coords[3],
GLdouble *vertex_data[4],
GLfloat weight[4], GLdouble **dataOut)
{
GLdouble *vertex;
int i;
vertex = (GLdouble *)malloc(6 * sizeof(GLdouble));
vertex[0] = coords[0];
vertex[1] = coords[1];
vertex[2] = coords[2];
for (i = 3; i < 6; i++)
vertex[i] = weight[0] * vertex_data[0][i]
+ weight[1] * vertex_data[1][i]
+ weight[2] * vertex_data[2][i]
+ weight[3] * vertex_data[3][i];
*dataOut = vertex;
}
void init(void)
{
GLUtesselator *tobj;
//矩形,三角形,五星顶点数据
GLdouble rect[4][3] = { 50.0, 50.0, 0.0,
200.0, 50.0, 0.0,
200.0, 250.0, 0.0,
50.0, 200.0, 0.0 };
GLdouble tri[3][3] = { 75.0, 75.0, 0.0,
125.0, 175.0, 0.0,
175.0, 75.0, 0.0 };
GLdouble star[5][6] = { 250.0, 50.0, 0.0, 1.0, 0.0, 1.0,
325.0, 200.0, 0.0, 1.0, 1.0, 0.0,
400.0, 50.0, 0.0, 0.0, 1.0, 1.0,
250.0, 150.0, 0.0, 1.0, 0.0, 0.0,
400.0, 150.0, 0.0, 0.0, 1.0, 0.0 };
glClearColor(0.0, 0.0, 0.0, 0.0);
startList = glGenLists(2);
//创建分格化对象
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);
glNewList(startList, GL_COMPILE);
glShadeModel(GL_FLAT);
gluTessBeginPolygon(tobj, NULL);//类似glBegin()
//矩形
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);//类似glEnd()
glEndList();
gluTessCallback(tobj, GLU_TESS_VERTEX,
(void(__stdcall*)())vertexCallback);
gluTessCallback(tobj, GLU_TESS_BEGIN,
(void(__stdcall*)())beginCallback);
gluTessCallback(tobj, GLU_TESS_END,
(void(__stdcall*)())endCallback);
gluTessCallback(tobj, GLU_TESS_ERROR,
(void(__stdcall*)())errorCallback);
gluTessCallback(tobj, GLU_TESS_COMBINE,
(void(__stdcall*)())combineCallback);
glNewList(startList + 1, GL_COMPILE);
glShadeModel(GL_SMOOTH);
//指定分格化属性
gluTessProperty(tobj, GLU_TESS_WINDING_RULE,
GLU_TESS_WINDING_NONZERO);//环绕数为正数则为内部区域
gluTessBeginPolygon(tobj, NULL);
gluTessBeginContour(tobj);
gluTessVertex(tobj, star[0], star[0]);
gluTessVertex(tobj, star[1], star[1]);
gluTessVertex(tobj, star[2], star[2]);
gluTessVertex(tobj, star[3], star[3]);
gluTessVertex(tobj, star[4], star[4]);
/*
GLU_TESS_WINDING_ODD 默认值,渲染环绕数为奇数的区域
GLU_TESS_WINDING_NONZERO 渲染环绕数不为0的区域
GLU_TESS_WINDING_POSITIVE 渲染环绕数为正的区域
GLU_TESS_WINDING_NEGATIVE 渲染环绕数为负的区域
GLU_TESS_WINDING_ABS_GEQ_TWO 渲染环绕数绝对值大于等于2的区域
*/
gluTessEndContour(tobj);
gluTessEndPolygon(tobj);
glEndList();
gluDeleteTess(tobj);//删除分格对象
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);
}
void keyboard(unsigned char key, int x, int y)
{
switch (key) {
case 27:
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}