【OpenGL】交互式三次 Bezier 曲线

1. 来源

  三次贝塞尔曲线就是依据四个位置任意的点坐标绘制出的一条光滑曲线

  

2. 公式

  

3. 实现

  

  1 #include <iostream>
  2 #include <math.h>
  3 #include <GL/gl.h>
  4 #include <GL/glut.h>
  5 #include <vector>
  6 //#include <pair>
  7 
  8 using namespace std;
  9 
 10 //points保存四个点
 11 vector<pair<GLfloat, GLfloat> > points;
 12 //设置两个bool变量来记录是否已经画出四个点之间的直线,以及相关贝塞尔曲线
 13 bool line = false;
 14 bool curve = false;
 15 
 16 //画直线
 17 void drawLine() {
 18     glColor3f(1.0f, 0, 0);
 19     glPointSize(1.0);
 20     for (int i = 0; i <= 2; i ++) {
 21         glBegin(GL_LINES);
 22             glVertex2f(points[i].first, points[i].second);
 23             glVertex2f(points[i+1].first, points[i+1].second); 
 24         glEnd();
 25     }
 26 }
 27 
 28 //贝塞尔曲线
 29 void drawCurve() {
 30     glColor3f(0, 1.0f, 0);
 31     glPointSize(1.0);
 32     for (GLfloat t = 0; t <= 1.0; t += 0.001) {
 33         GLfloat x = points[0].first*pow(1.0f-t, 3) + 3*points[1].first*t*pow(1.0f-t, 2) + 3*points[2].first*t*t*(1.0f-t) + points[3].first*pow(t, 3);
 34         GLfloat y =  points[0].second*pow(1.0f-t, 3) + 3*points[1].second*t*pow(1.0f-t, 2) + 3*points[2].second*t*t*(1.0f-t) + points[3].second*pow(t, 3);
 35         glBegin(GL_POINTS);
 36             glVertex2f(x, y);
 37         glEnd();
 38     }
 39 }
 40 
 41 //初始化函数
 42 void myInit() {
 43     glClearColor(0, 0, 0, 0);
 44     glColor3f(1.0f, 0, 0);
 45     glPointSize(5.0);
 46     glMatrixMode(GL_MODELVIEW);
 47     glLoadIdentity();
 48     gluOrtho2D(0.0, 500, 0.0, 500);
 49 }
 50 
 51  void myDisplay() { 
 52     glClear(GL_COLOR_BUFFER_BIT);
 53     glFlush();
 54 }
 55 
 56 //对于鼠标点击的响应函数
 57 void myMouse(int button, int state, int x, int y)
 58 {
 59     //按下鼠标左键
 60      if(state==GLUT_DOWN)
 61      {
 62         //画4个点
 63         if (points.size() < 4) {
 64             glBegin(GL_POINTS);
 65                 glVertex2i(x, 500 - y);
 66             glEnd();
 67             points.push_back(make_pair(GLfloat(x), GLfloat(500 - y)));
 68         }
 69         //若已经画好四个点,则开始画点连成的线段\曲线
 70         else if (points.size() == 4) {
 71             //线段
 72             if (line == false) {
 73                 drawLine();
 74                 line = true;
 75             }
 76             //曲线
 77             else if (line == true && curve == false) {
 78                 drawCurve();
 79                 curve = true;
 80             }
 81             //清空
 82             else if (line == true && curve == true) {
 83                 glClear(GL_COLOR_BUFFER_BIT);
 84                 glColor3f(1.0f, 0, 0);
 85                 glPointSize(5.0);
 86                 line = false;
 87                 curve = false;
 88                 while(!points.empty()) {
 89                     points.pop_back();
 90                 }
 91             }
 92         }
 93         glFlush();
 94      }
 95  }
 96 
 97 int main(int argc, char** argv) {
 98     glutInit(&argc, argv);
 99     glutInitDisplayMode(GLUT_RGB);
100     glutInitWindowPosition(0, 0);
101     glutInitWindowSize(500, 500);
102     glutCreateWindow("Bezier-curve");
103 
104     myInit();
105     glutDisplayFunc (myDisplay);
106     glutMouseFunc(myMouse);
107     glutMainLoop();
108     return 0;
109 }

 

4. 延伸

  一次、二次、五次贝赛尔曲线以及贝塞尔曲线的升阶,具体:

  https://zh.wikipedia.org/zh-cn/%E8%B2%9D%E8%8C%B2%E6%9B%B2%E7%B7%9A

 

posted @ 2016-05-11 16:36  CheerM  阅读(5233)  评论(0编辑  收藏  举报