C++ 使用 OpenGL 绘制二次贝塞尔曲线函数代码解析
#include
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; }
代码解释
- 定义点结构体
typedef struct point {
float x;
float y;
} POINT;
该结构体用于表示二维空间中的一个点,包含横坐标 x 和纵坐标 y。
- 初始化绘图环境
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)。
- 绘制点函数
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()渲染所有绘制的图形。
- 计算贝塞尔曲线点函数
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的点坐标。
- 绘制贝塞尔曲线函数
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()渲染所有绘制的图形。
- 绘制函数
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)。
- 主函数
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 绘制了一个二次贝塞尔曲线。通过代码注释可以了解到,绘制贝塞尔曲线主要包括以下几个步骤:
- 定义点结构体,用于存储点的坐标。
- 初始化 OpenGL 绘图环境。
- 定义计算贝塞尔曲线点坐标的函数。
- 定义绘制点的函数。
- 定义绘制贝塞尔曲线函数,使用循环遍历参数
t计算出贝塞尔曲线上的点坐标,并绘制这些点。 - 定义绘制函数,调用绘制贝塞尔曲线函数。
- 使用 GLUT 库创建窗口,设置回调函数,进入主循环等待用户交互。
通过理解这些步骤,可以更好地理解 OpenGL 图形绘制的基本原理。
原文地址: http://www.cveoy.top/t/topic/n31z 著作权归作者所有。请勿转载和采集!