opengl进阶技巧(一)使用glut来绘制凹多边形

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;
}
发布了194 篇原创文章 · 获赞 8 · 访问量 9861

猜你喜欢

转载自blog.csdn.net/qq_43439240/article/details/104230200