OpenGL绘制平面五角星并为中心着色

OpenGL绘制平面五角星并为中心着色


北京航空航天大学计算机学院 2020春季计算机图形学课程第一次作业,使用OpenGL绘制平面的五角星,并为中心着色,目标结果如下图:
在这里插入图片描述


基本熟悉OpenGL绘图流程之后,我们按照要求绘制相应的五角星。思路是:首先我们找到五角星的五个顶点,实际上就是正五边形的顶点,然后将正五边形顺序的顶点映射到五角星顺序的顶点,通过OpenGL函数中指定绘制顶点相互连接最终成环即可绘制出基本的五角星。观察要求的图示,还需要知晓五角星中间所围成小五边形的顶点坐标,利用绘制三角扇来为中心着色。最后是五角星的五个顶点是圆形的点,通过多边形逼近圆形来绘制五个顶点。

其中五角星的角度是可以旋转的,不加旋转的五角星并没有水平的边,若想要五角星呈现我们平时所见到的“正”的姿态,需要在直接绘制的正五边形顶点基础上逆时针转18度。

在计算五角星中心的正五边形顶点时,需要用到分别已知两直线上的两点,求两直线交点,该公式在博主的另一篇博客里有详细解析。

代码和其注释如下:

#include<GL/glut.h>
#include<math.h>
#define PI 3.1415926
#define SIZE 600

double pentagram_vertex[5][2];
double pentagon_vertex[5][2];

void get_pentagram() 
{
	// 五角星看作在圆上内接的五边形的顶点连成的,此处设置外接圆半径[0, 1]
	double r = (SIZE * 0.5);
	// 五角星可以在外接圆上旋转,此处设置旋转角度[0, 360)
	double rotate = 18;
	// 依次通过外接圆计算正五边形的五个顶点横纵坐标
	double tmp[5][2];
	for (int i = 0; i < 5; i++) {
		tmp[i][0] = r * cos(((72 * (double)i + rotate) / 360) * (2 * PI));
		tmp[i][1] = r * sin(((72 * (double)i + rotate) / 360) * (2 * PI));
	}
	// 将正五边形顺序的五个顶点对应到五角星顺序的五个顶点(0, 1, 2, 3, 4) -> (0, 2, 4, 1, 3)
	for (int i = 0, j = 0; i < 5; i++, j = j + 2) {
		int k = j % 5;
		pentagram_vertex[i][0] = tmp[k][0];
		pentagram_vertex[i][1] = tmp[k][1];
	}

	// 五角星的边相交得到中间的小五边形顶点,计算以便绘图时的着色
	double x[4], y[4];
	for (int i = 0; i < 5; i++) {
		int v[4];
		for (int j = 0; j < 4; j++)
			v[j] = (i + j) % 5;
		for (int j = 0; j < 4; j++)
			x[j] = pentagram_vertex[v[j]][0], y[j] = pentagram_vertex[v[j]][1];
		tmp[i][0] = ((x[2] - x[3]) * (x[1] * y[0] - x[0] * y[1]) 
			- (x[0] - x[1]) * (x[3] * y[2] - x[2] * y[3])) / 
			((x[2] - x[3]) * (y[0] - y[1]) - (x[0] - x[1]) * (y[2] - y[3]));
		tmp[i][1] = ((y[2] - y[3]) * (y[1] * x[0] - y[0] * x[1])
			- (y[0] - y[1]) * (y[3] * x[2] - y[2] * x[3])) /
			((y[2] - y[3]) * (x[0] - x[1]) - (y[0] - y[1]) * (x[2] - x[3]));
	}
	for (int i = 0, j = 0; i < 5; i++, j = j + 2) {
		int k = j % 5;
		pentagon_vertex[i][0] = tmp[k][0];
		pentagon_vertex[i][1] = tmp[k][1];
	}
}

void initial()
{
	glClearColor(1.0, 1.0, 1.0, 1.0);
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(-(SIZE * 0.6), (SIZE * 0.6), -(SIZE * 0.6), (SIZE * 0.6));
	get_pentagram();
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT);

	// 下面的段落绘制五角星中心所围成小正五边形的着色
	glColor3f(1.0, 1.0, 0.0);
	glBegin(GL_TRIANGLE_FAN);
	for (int i = 0; i < 5; i++)
		glVertex2d(pentagon_vertex[i][0], pentagon_vertex[i][1]);
	glEnd();

	// 下面的段落绘制五角星的线
	glColor3f(0.0, 0.0, 0.0);
	// 启用抗锯齿(使线平滑)
	glEnable(GL_BLEND);
	glEnable(GL_LINE_SMOOTH);
	glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	// 设置线的宽度(0, 10]
	glLineWidth(5);
	glBegin(GL_LINE_LOOP);
	for (int i = 0; i < 5; i++)
		glVertex2d(pentagram_vertex[i][0], pentagram_vertex[i][1]);
	glEnd();

	// 下面的段落绘制五角星的五个顶点(实心圆)
	glColor3f(0.0, 0.0, 0.0);
	// 设置实心圆的半径
	double radius = 8;
	// 设置用来拟合圆形的多边形边个数
	int sections = 200;
	for (int i = 0; i < 5; i++) {
		glBegin(GL_TRIANGLE_FAN);
		glVertex2d(pentagram_vertex[i][0], pentagram_vertex[i][1]);
		for (int j = 0; j <= sections; j++)
			glVertex2d(pentagram_vertex[i][0] + radius * cos(j * 2 * PI / sections),
				pentagram_vertex[i][1] + radius * sin(j * 2 * PI / sections));
		glEnd();
	}

	glFlush();
}

int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);

	glutInitWindowPosition(100, 100);
	glutInitWindowSize(SIZE, SIZE);
	glutCreateWindow("Pentagram");

	glutDisplayFunc(&display);
	initial();
	glutMainLoop();

	return 0;
}

绘制结果与要求的图示大致相同了:

在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值