1.实验目的
掌握Bezier曲线的定义原理及绘制过程
定义:
贝塞尔曲线(Bezier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。
2. 实验要求:
利用OpenGL实现一个三次Bezier曲线,任意输入四个控制点,绘制出对应的贝塞尔曲线;并通过鼠标调整控制点(随机变化或沿某种图案变化)让曲线动态显示。
3.实验代码(部分)
需要先安装glut库
#include<GL/glut.h>
#include<GL/GL.h>
#include<math.h>
void mouseClick(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON)
{
if (state == GLUT_DOWN) {
if (mask == -1) {
for (int i = 0; i < 4; i++)
{
float mouse_x = (x - 200) / 200.0f, mouse_y = (200 - y) / 200.0f;
float dis = sqrt((mouse_x - ctrl_points[i][0]) * (mouse_x - ctrl_points[i][0]) + (mouse_y - ctrl_points[i][1]) * (mouse_y - ctrl_points[i][1]));
if (dis < 0.1f) mask = i;
}
}
}
else if (state == GLUT_UP)
mask = -1;
}
}
deCateljau算法:
在C++中,Bezier曲线常使用deCateljau算法生成,其思想就是每一次都遍历相邻的控制点,根据给定参数t在两相邻控制点形成的线段上取一个新的控制点。这样,每遍历一遍之前的控制点后生成的新控制点会更加逼近Bezier曲线,且控制点的数量减1,当最后只剩一个控制点时,可以将这个控制点视为Bezier曲线上的点。
void de_Cateljau(int n, GLfloat list[][2])
{
float R_x[4];
float R_y[4];
int k = 0;
for (double t = 0.0; t <= 1; t += 0.1)
{
for (int i = 0; i < n; i++) {
R_x[i] = ctrl_points[i][0];
R_y[i] = ctrl_points[i][1];
}
for (int i = 1; i < n; i++)
{
for (int j = 0; j < n - i; j++)
{
R_x[j] = (1 - t) * R_x[j] + t * R_x[j + 1];
R_y[j] = (1 - t) * R_y[j] + t * R_y[j + 1];
}
}
list[k][0] = R_x[0];
list[k][1] = R_y[0];
k++;
}
}
绘制函数:
void display() {
glClearColor(1.0, 1.0, 1.0, 1.0);//(R,G,B,alpha)自己设置
glClear(GL_COLOR_BUFFER_BIT);//当前可写的颜色缓冲
glPointSize(3);
glColor3f(0.53,0.51,0.78);
for (int i = 0; i < 4; i++) {
glBegin(GL_POINTS);//把每个顶点作为一个点进行处理,顶点n定义了点n,绘制N个点。
glVertex2fv(&ctrl_points[i][0]);
glEnd();
}
glColor3f(0.53,0.51,0.78);
glBegin(GL_LINE_STRIP);//绘制从第一个顶点到最后一个顶点依次相连的一组线段,第n和n+1个顶点定义了线段n,绘制n-1条线段
for (int i = 0; i < 4; i++) {
glVertex2fv(&ctrl_points[i][0]);
}
glEnd();
GLfloat pos_list[11][2] = { 0 };
de_Cateljau(4, pos_list);
glColor3f(1.0, 1.0, 0.0);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < 11; i++) {
glVertex2fv(pos_list[i]);//指定顶点
}
glEnd();
glFlush();//强制刷新缓冲,保证绘图命令将被执行
}
4.结果样例图
可以拖动任意点改变bezier曲线的形状。完整源码点这里获取。