前言
初学计算机图形学以及VS、OpenGL,只作为参考,无权威性可言,有问题欢迎大家在评论区提出,如果帮到你了,可以留个点赞再走。
一、核心思路
五角星的十个顶点由同心圆的十个顶点构成。通过同心圆的圆心坐标、大圆半径R、小圆半径r计算出十个顶点的坐标,然后通过绘制线段/三角形来绘制五角星。(计算比较简单,根据下图即可计算出十个顶点的坐标,这里就省略了)
二、源码
#include <GL/glew.h>//OpenGL扩展库
#include <GL/glut.h>//OpenGL工具库
#include <stdio.h>
#include <math.h>
// 绘制五角星核心思路:求出五角星的十个顶点再通过绘制线段/三角形连接起来即可
// 定义Π
#define PI 3.14159265
// 定义坐标结构体
struct Vertex {
double x;
double y;
};
// 绘制线段函数
void drawLine(Vertex Vertex_Fir, Vertex Vertex_Sec) {
// 设置颜色
glColor3f(1, 0, 0);
// 设置绘制类型
glBegin(GL_LINES);
// 第一个坐标
glVertex2f(Vertex_Fir.x, Vertex_Fir.y);
// 第二个坐标
glVertex2f(Vertex_Sec.x, Vertex_Sec.y);
glEnd();
}
// 绘制红色三角形函数
void drawRedTriangle(Vertex Vertex_Fir, Vertex Vertex_Sec, Vertex Vertex_Thi) {
// 设置填充的颜色
glColor3f(1, 0, 0);
// 设置绘制类型
glBegin(GL_TRIANGLES);
// 第一个坐标
glVertex2f(Vertex_Fir.x, Vertex_Fir.y);
// 第二个坐标
glVertex2f(Vertex_Sec.x, Vertex_Sec.y);
// 第三个坐标
glVertex2f(Vertex_Thi.x, Vertex_Thi.y);
glEnd();
}
// 绘制蓝色三角形函数
void drawBlueTriangle(Vertex Vertex_Fir, Vertex Vertex_Sec, Vertex Vertex_Thi) {
// 设置填充的颜色
glColor3f(0, 0, 255);//深蓝色
// 设置绘制类型
glBegin(GL_TRIANGLES);
// 第一个坐标
glVertex2f(Vertex_Fir.x, Vertex_Fir.y);
// 第二个坐标
glVertex2f(Vertex_Sec.x, Vertex_Sec.y);
// 第三个坐标
glVertex2f(Vertex_Thi.x, Vertex_Thi.y);
glEnd();
}
// 获取外圆五角星的五顶点(参数:大圆圆心坐标以及半径)
Vertex* getExternalVertex(Vertex Center_Vertex, double R) {
// 定义Vertex结构体数组,包括五个顶点和一个圆心
Vertex* externalVertex = new Vertex[6];
double alpha = 2*PI / 5;
double thet = PI / 10;
double bet = 2*PI / 10;
// 圆心坐标
externalVertex[0].x = Center_Vertex.x, externalVertex[0].y = Center_Vertex.y;
// 其余五个顶点
externalVertex[1].x = Center_Vertex.x, externalVertex[1].y = Center_Vertex.y+R;
externalVertex[2].x = Center_Vertex.x+R*cos(thet), externalVertex[2].y = Center_Vertex.y+R*sin(thet);
externalVertex[3].x = Center_Vertex.x+R*sin(bet), externalVertex[3].y = Center_Vertex .y-R*cos(bet);
externalVertex[4].x = Center_Vertex.x-R*sin(bet), externalVertex[4].y = Center_Vertex.y-R*cos(bet);
externalVertex[5].x = Center_Vertex.x-R*cos(thet), externalVertex[5].y = Center_Vertex.y+R*sin(thet);
return externalVertex;
}
// 获取内圆五角星的五顶点(参数:小圆圆心坐标以及半径)
Vertex* getInternalVertex(Vertex Center_Vertex, double r) {
// 定义Vertex结构体数组,包括五个顶点和一个圆心
Vertex* internalVertex = new Vertex[6];
double alpha = 2 * PI / 5;
double thet = PI / 10;
double bet = (PI-alpha) / 2;
// 圆心坐标
internalVertex[0].x = Center_Vertex.x, internalVertex[0].y = Center_Vertex.y;
// 其余五个顶点
internalVertex[1].x = Center_Vertex.x + r * cos(bet), internalVertex[1].y = Center_Vertex.y + r * sin(bet);
internalVertex[2].x = Center_Vertex.x + r * cos(thet), internalVertex[2].y = Center_Vertex.y - r * sin(thet);//
internalVertex[3].x = Center_Vertex.x, internalVertex[3].y = Center_Vertex.y - r;//
internalVertex[4].x = Center_Vertex.x - r * cos(thet), internalVertex[4].y = Center_Vertex.y - r * sin(thet);
internalVertex[5].x = Center_Vertex.x - r * cos(bet), internalVertex[5].y = Center_Vertex.y + r * sin(bet);
return internalVertex;
}
// 设置背景颜色
void setBackgroundColor(void) {
glClearColor(0.2, 0.3, 0.3, 0.5);
}
// 绘制五角星
void draw(void) {
// 清除清缓存
glClear(GL_COLOR_BUFFER_BIT);
// ### 绘制线框五角星 ###
// 1. 定义圆心、大小圆半径
Vertex Center_Vertex;
Center_Vertex.x = 500, Center_Vertex.y =150;//圆心以显示窗口的左下角为原点,向右x轴正方向,向上y轴正方向
double R = 100;
double r = 40;
// 2. 获取内外顶点
Vertex* externalVertex = getExternalVertex(Center_Vertex, R);
Vertex* internalVertex = getInternalVertex(Center_Vertex, r);
// 3. 绘制线框五角星
for (int i = 1; i < 6; i++) {
drawLine(externalVertex[i], internalVertex[i]);
if (i < 5) {
drawLine(internalVertex[i], externalVertex[i + 1]);
}
else {
drawLine(internalVertex[i], externalVertex[1]);
}
}
// ### 绘制红色五角星 ###
// 1. 定义圆心、大小圆半径
Center_Vertex.x = 500, Center_Vertex.y = 350;
R = 100, r = 40;
// 2. 获取内外顶点
externalVertex = getExternalVertex(Center_Vertex, R);
internalVertex = getInternalVertex(Center_Vertex, r);
// 3. 绘制红色五角星
for (int i = 1; i < 6; i++) {
drawRedTriangle(Center_Vertex, internalVertex[i], externalVertex[i]);
if (i < 5) {
drawRedTriangle(Center_Vertex, internalVertex[i], externalVertex[i+1]);
}
else {
drawRedTriangle(Center_Vertex, internalVertex[i], externalVertex[1]);
}
}
// ### 绘制多色五角星 ###
// 1. 定义圆心、大小圆半径
Center_Vertex.x = 500, Center_Vertex.y = 550;
R = 100, r = 40;
// 2. 获取内外顶点
externalVertex = getExternalVertex(Center_Vertex, R);
internalVertex = getInternalVertex(Center_Vertex, r);
// 3. 绘制多色五角星
for (int i = 1; i < 6; i++) {
// 绘制红色三角形
drawRedTriangle(Center_Vertex, internalVertex[i], externalVertex[i]);
// 绘制蓝色三角形
if (i < 5) {
drawBlueTriangle(Center_Vertex, internalVertex[i], externalVertex[i + 1]);
}
else {
drawBlueTriangle(Center_Vertex, internalVertex[i], externalVertex[1]);
}
}
glutSwapBuffers();//交换缓冲(双缓冲时使用)
}
void reshape(int width, int height)
{
glViewport(0, 0, width, height);//设置视区
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width, 0, height);//设置图形数据范围
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main() {
// 窗口的坐标是电脑屏幕左上角为原点,向右为x轴正方向;向下为y轴正方向
glutInitWindowPosition(100, 100); //定义窗口位置与大小
glutInitWindowSize(1200, 700);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); //初始化显示模式
glutCreateWindow("五角星"); //定义窗口名称
setBackgroundColor(); // 设置背景色
glutDisplayFunc(draw); //图形绘制函数
glutReshapeFunc(reshape); //窗口重绘函数
glutMainLoop(); //无限循环函数
return 0;
}
三、其他小知识
-
定义显示窗口位置与大小时:参考坐标系是电脑屏幕左上角为原点,向右为x轴正方向;向下为y轴正方向
-
绘制图形时使用的坐标:参考坐标系是显示窗口的左下角为原点,向右x轴正方向,向上y轴正方向