#include #include <gl/glut.h> // 引入 OpenGL 和 GLUT 库

using namespace std;

typedef struct point { // 定义一个结构体,用来表示点的坐标 float x; float y; } POINT;

void init() { glClearColor(1.0, 1.0, 1.0, 1.0); // 设置背景颜色为白色 glMatrixMode(GL_PROJECTION); // 设置矩阵模式为投影模式 glLoadIdentity(); // 将当前矩阵重置为单位矩阵 gluOrtho2D(0.0, 200.0, 0.0, 150.0); // 设置二维正交投影 }

void setPoints(POINT v) { // 设置函数用于绘制点 glBegin(GL_POINTS); // 开始绘制点

glVertex2f(v.x, v.y);  // 绘制点的坐标

glEnd();  // 结束绘制
glFinish();  // 渲染所有绘制图形

}

POINT set2Bezier(POINT p0, POINT p1, POINT p2, POINT p3, float t) { // 计算二次贝塞尔曲线上的点 POINT pt; float a0 = (1 - t) * (1 - t) * (1 - t); float a1 = 3 * t * (1 - t) * (1 - t); float a2 = 3 * t * t * (1 - t); float a3 = t * t * t;

pt.x = a0 * p0.x + a1 * p1.x + a2 * p2.x + a3 * p3.x;  // 计算 x 坐标
pt.y = a0 * p0.y + a1 * p1.y + a2 * p2.y + a3 * p3.y;  // 计算 y 坐标

return pt;  // 返回计算出的点的坐标

}

void draw2Bezier(float X, float Y) { // 绘制二次贝塞尔曲线 POINT p[4]; // 定义四个点,确定二次贝塞尔曲线的形状 p[0].x = X + 30; p[0].y = Y + 50; // 第一个点的坐标 p[1].x = X + 10; p[1].y = Y + 30; // 第二个点的坐标 p[2].x = X + 100; p[2].y = Y + 70; // 第三个点的坐标 p[3].x = X + 150; p[3].y = Y + 30; // 第四个点的坐标

POINT pt;
for (float t = 0; t <= 1; t += 0.01) {  // 计算二次贝塞尔曲线上的点,并绘制
	pt = set2Bezier(p[0], p[1], p[2], p[3], t);
	setPoints(pt);
}

glColor3f(1.0, 1.0, 1.0);  // 设置颜色为白色
glBegin(GL_LINES);  // 开始绘制线段

glVertex2d(p[0].x, p[0].y);  // 绘制线段的起点
glVertex2d(p[1].x, p[1].y);  // 绘制线段的终点

glVertex2d(p[1].x, p[1].y);  // 绘制线段的起点
glVertex2d(p[2].x, p[2].y);  // 绘制线段的终点

glVertex2d(p[2].x, p[2].y);  // 绘制线段的起点
glVertex2d(p[3].x, p[3].y);  // 绘制线段的终点

glEnd();  // 结束绘制线段
glFlush();  // 渲染所有绘制图形

}

void display() { glClear(GL_PROJECTION); // 清空投影矩阵

glColor3f(1.0, 0, 0);  // 设置颜色为红色
draw2Bezier(10, 10);  // 绘制二次贝塞尔曲线,起点坐标为 (10, 10)

}

int main(int argc, char** argv) { glutInit(&argc, argv); // 初始化 GLUT 库 glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // 设置显示模式为单缓存、RGB 色 glutInitWindowPosition(100, 100); // 设置窗口的初始位置 glutInitWindowSize(400, 400); // 设置窗口大小 glutCreateWindow('Lines'); // 创建窗口并设置窗口名称 init(); // 初始化绘图环境 glutDisplayFunc(display); // 设置回调函数 glutMainLoop(); // 进入主循环,等待用户交互 return 0; }

代码解释

  1. 定义点结构体
typedef struct point {
	float x;
	float y;
} POINT;

该结构体用于表示二维空间中的一个点,包含横坐标 x 和纵坐标 y

  1. 初始化绘图环境
void init() {
	glClearColor(1.0, 1.0, 1.0, 1.0);  // 设置背景颜色为白色
	glMatrixMode(GL_PROJECTION);  // 设置矩阵模式为投影模式
	glLoadIdentity();  // 将当前矩阵重置为单位矩阵
	gluOrtho2D(0.0, 200.0, 0.0, 150.0);  // 设置二维正交投影
}

init() 函数用于初始化 OpenGL 绘图环境。

  • glClearColor(1.0, 1.0, 1.0, 1.0) 设置背景颜色为白色 (RGBA: 1, 1, 1, 1)。
  • glMatrixMode(GL_PROJECTION) 设置当前矩阵模式为投影模式。
  • glLoadIdentity() 将当前矩阵重置为单位矩阵。
  • gluOrtho2D(0.0, 200.0, 0.0, 150.0) 设置二维正交投影,坐标范围为 (0, 0) 到 (200, 150)。
  1. 绘制点函数
void setPoints(POINT v) {
	glBegin(GL_POINTS);  // 开始绘制点

	glVertex2f(v.x, v.y);  // 绘制点的坐标

	glEnd();  // 结束绘制
	glFinish();  // 渲染所有绘制图形
}

setPoints() 函数用于绘制单个点。

  • glBegin(GL_POINTS) 开始绘制点。
  • glVertex2f(v.x, v.y) 指定点的坐标。
  • glEnd() 结束绘制。
  • glFinish() 渲染所有绘制的图形。
  1. 计算贝塞尔曲线点函数
POINT set2Bezier(POINT p0, POINT p1, POINT p2, POINT p3, float t) {
	POINT pt;
	float a0 = (1 - t) * (1 - t) * (1 - t);
	float a1 = 3 * t * (1 - t) * (1 - t);
	float a2 = 3 * t * t * (1 - t);
	float a3 = t * t * t;

	pt.x = a0 * p0.x + a1 * p1.x + a2 * p2.x + a3 * p3.x;  // 计算 x 坐标
	pt.y = a0 * p0.y + a1 * p1.y + a2 * p2.y + a3 * p3.y;  // 计算 y 坐标

	return pt;  // 返回计算出的点的坐标
}

set2Bezier() 函数用于计算二次贝塞尔曲线上的点。

  • p0, p1, p2, p3 分别代表贝塞尔曲线的起点,第一个控制点,第二个控制点和终点。
  • t 代表参数,取值范围为 [0, 1],用于确定贝塞尔曲线上的点的位置。
  • 函数使用贝塞尔曲线公式计算出对应参数 t 的点坐标。
  1. 绘制贝塞尔曲线函数
void draw2Bezier(float X, float Y) {
	POINT p[4];  // 定义四个点,确定二次贝塞尔曲线的形状
	p[0].x = X + 30; p[0].y = Y + 50;  // 第一个点的坐标
	p[1].x = X + 10; p[1].y = Y + 30;  // 第二个点的坐标
	p[2].x = X + 100; p[2].y = Y + 70;  // 第三个点的坐标
	p[3].x = X + 150; p[3].y = Y + 30;  // 第四个点的坐标

	POINT pt;
	for (float t = 0; t <= 1; t += 0.01) {
		pt = set2Bezier(p[0], p[1], p[2], p[3], t);
		setPoints(pt);
	}

	glColor3f(1.0, 1.0, 1.0);  // 设置颜色为白色
	glBegin(GL_LINES);  // 开始绘制线段

	glVertex2d(p[0].x, p[0].y);  // 绘制线段的起点
	glVertex2d(p[1].x, p[1].y);  // 绘制线段的终点

	glVertex2d(p[1].x, p[1].y);  // 绘制线段的起点
	glVertex2d(p[2].x, p[2].y);  // 绘制线段的终点

	glVertex2d(p[2].x, p[2].y);  // 绘制线段的起点
	glVertex2d(p[3].x, p[3].y);  // 绘制线段的终点

	glEnd();  // 结束绘制线段
	glFlush();  // 渲染所有绘制图形
}

draw2Bezier() 函数用于绘制二次贝塞尔曲线。

  • 定义四个点 p[4],分别为贝塞尔曲线的起点,两个控制点,以及终点。
  • 使用循环遍历参数 t 从 0 到 1,计算出对应每个 t 值的贝塞尔曲线上的点坐标,并使用 setPoints() 函数绘制这些点。
  • 使用 glColor3f(1.0, 1.0, 1.0) 设置线条颜色为白色。
  • 使用 glBegin(GL_LINES) 开始绘制线段,连接四个点,绘制贝塞尔曲线的控制线。
  • glEnd() 结束绘制。
  • glFlush() 渲染所有绘制的图形。
  1. 绘制函数
void display() {
	glClear(GL_PROJECTION);  // 清空投影矩阵

	glColor3f(1.0, 0, 0);  // 设置颜色为红色
	draw2Bezier(10, 10);  // 绘制二次贝塞尔曲线,起点坐标为 (10, 10)
}

display() 函数用于绘制所有需要显示的图形。

  • glClear(GL_PROJECTION) 清空投影矩阵。
  • glColor3f(1.0, 0, 0) 设置颜色为红色。
  • draw2Bezier(10, 10) 绘制二次贝塞尔曲线,起点坐标为 (10, 10)。
  1. 主函数
int main(int argc, char** argv)
{
	glutInit(&argc, argv);  // 初始化 GLUT 库
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);  // 设置显示模式为单缓存、RGB 色
	glutInitWindowPosition(100, 100);  // 设置窗口的初始位置
	glutInitWindowSize(400, 400);  // 设置窗口大小
	glutCreateWindow('Lines');  // 创建窗口并设置窗口名称
	init();  // 初始化绘图环境
	glutDisplayFunc(display);  // 设置回调函数
	glutMainLoop();  // 进入主循环,等待用户交互
	return 0;
}

main() 函数是程序的入口函数。

  • glutInit(&argc, argv) 初始化 GLUT 库。
  • glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB) 设置显示模式为单缓存、RGB 色。
  • glutInitWindowPosition(100, 100) 设置窗口的初始位置。
  • glutInitWindowSize(400, 400) 设置窗口大小。
  • glutCreateWindow('Lines') 创建窗口并设置窗口名称。
  • init() 初始化绘图环境。
  • glutDisplayFunc(display) 设置回调函数,当需要绘制图形时调用 display() 函数。
  • glutMainLoop() 进入主循环,等待用户交互。

总结

该代码利用 OpenGL 绘制了一个二次贝塞尔曲线。通过代码注释可以了解到,绘制贝塞尔曲线主要包括以下几个步骤:

  1. 定义点结构体,用于存储点的坐标。
  2. 初始化 OpenGL 绘图环境。
  3. 定义计算贝塞尔曲线点坐标的函数。
  4. 定义绘制点的函数。
  5. 定义绘制贝塞尔曲线函数,使用循环遍历参数 t 计算出贝塞尔曲线上的点坐标,并绘制这些点。
  6. 定义绘制函数,调用绘制贝塞尔曲线函数。
  7. 使用 GLUT 库创建窗口,设置回调函数,进入主循环等待用户交互。

通过理解这些步骤,可以更好地理解 OpenGL 图形绘制的基本原理。

C++ 使用 OpenGL 绘制二次贝塞尔曲线函数代码解析

原文地址: http://www.cveoy.top/t/topic/n31z 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录