OpenGL绘制贝塞尔曲线

时间:2021-05-20

本文实例为大家分享了OpenGL绘制贝塞尔曲线的具体代码,供大家参考,具体内容如下

最终效果图:

通过3个点形成一条贝塞尔曲线

1. 鼠标问题

在使用鼠标获取坐标的时候,要知道鼠标获取的坐标和屏幕坐标是不同的;

openGL使用右手坐标
从左到右,x递增
从下到上,y递增
从远到近,z递增

而鼠标是从左到右增x,同时从上到下也是增y

所以在求 y 的时候,用(屏幕大小-y)来获取

2. 绘制

setpoint 用来绘制点
setline 用来绘制线
setBezier 用来绘制贝塞尔曲线

其中公式的意义可以参考百科:

实际绘制的时候就是不断的增加t,求出下一点的值然后将两个链接起来,然后再将下一个点作为起点,再求出下下一个点

Api解释在代码中

#include "GL\glut.h"#include <math.h>#include <Windows.h>//这是一个点的类,用于存储其中点的坐标class Point{public: int x, y; void setxy(int _x, int _y) { x = _x; y = _y; }};//点的数量static int POINTSNUM = 0;//用于存储点的集合,因为绘制的都是4个点的贝塞尔曲线,所以数组大小为4static Point points[4];//初始化函数void init(void){ glClearColor(1.0, 1.0, 1.0, 0); //设定背景为黑色 glColor3f(0.0,0.0,0.0); //绘图颜色为白色 glPointSize(2.0); //设定点的大小为2*2像素的 glMatrixMode(GL_PROJECTION); // 设定合适的矩阵 glLoadIdentity(); // 是一个无参的无值函数,其功能是用一个4×4的单位矩阵来替换当前矩阵,实际上就是对当前矩阵进行初始化。也就是说,无论以前进行了多少次矩阵变换,在该命令执行后,当前矩阵均恢复成一个单位矩阵,即相当于没有进行任何矩阵变换状态 gluOrtho2D(0.0,600.0,0.0,480.0); //平行投影,四个参数分别是x,y范围}//绘制点void setPoint(Point p) { glBegin(GL_POINTS); glVertex2f(p.x, p.y); glEnd(); glFlush();}// 绘制直线void setline(Point p1, Point p2) { glBegin(GL_LINES); glVertex2f(p1.x,p1.y); glVertex2f(p2.x, p2.y); glEnd(); glFlush();}// 绘制贝塞尔曲线Point setBezier(Point p1, Point p2, Point p3, Point p4,double t) { Point p; double a1 = pow((1 - t), 3); double a2 = pow((1 - t), 2) * 3 * t; double a3 = 3 * t*t*(1 - t); double a4 = t*t*t; p.x = a1*p1.x + a2*p2.x + a3*p3.x + a4*p4.x; p.y = a1*p1.y + a2*p2.y + a3*p3.y + a4*p4.y; return p;}//display函数void display(){ glClear(GL_COLOR_BUFFER_BIT); glFlush();}// 鼠标事件void mymouseFunction(int button, int state, int x, int y) { if (state == GLUT_DOWN) // 如果鼠标按下,不区分左右键的 { points[POINTSNUM].setxy(x,480- y); // 这里求鼠标点的坐标的时候 // 设置点的颜色,绘制点 glColor3f(1.0,0.0,0.0); setPoint(points[POINTSNUM]); // 设置线的颜色,绘制线 glColor3f(1.0,0.0,0.0); if(POINTSNUM > 0) setline(points[POINTSNUM-1],points[POINTSNUM]); //如果达到了4个绘制贝塞尔曲线,并在之后给计数器清零 if (POINTSNUM == 3) { //绘制贝塞尔曲线 glColor3f(0.0, 0.0, 1.0); // 设定贝塞尔曲线的颜色 Point p_current = points[0]; //设为起点 for (double t = 0.0; t <= 1.0; t += 0.05) { Point P = setBezier(points[0], points[1], points[2], points[3], t); setline(p_current, P); p_current = P; } POINTSNUM = 0; } else { POINTSNUM++; } }}int main(int argc, char *argv[]){ glutInit(&argc, argv); //固定格式 glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //缓存模式 glutInitWindowSize(600, 480); //显示框的大小 glutInitWindowPosition(100, 100); //确定显示框左上角的位置 glutCreateWindow("第四次作业"); init(); // 初始化 glutMouseFunc(mymouseFunction); // 添加鼠标事件 glutDisplayFunc(display); // 执行显示 glutMainLoop(); //进人GLUT事件处理循环 return 0;}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章