zoukankan      html  css  js  c++  java
  • OpenGL绘制简单的参数曲线(二)——三次Bezier曲线

      今天我们来介绍三次Bezier曲线,这曲线网上资料非常多,我这里只是简单介绍下原理。

      在二维空间中(三维也类似),给定n+1个点P0P1、... 、Pn。参数tn次的Bezier曲线是:

    图1

      我们根据上面式子可以推出一次、二次、三次贝塞尔曲线,下面是一次贝塞尔曲线:

     

    图2

      下面是二次贝塞尔曲线,表示的是从P0P1线段取Q0P1P2线段取Q1,每一个Q0Q1都是曲线的切向量:

    图3

      下面是三次贝塞尔曲线,表示的是从P0P1线段取Q0P1P2线段取Q1P2P3线段取Q2,再从Q0Q1R0Q1Q2R1,每一个R0R1都是曲线的切向量:

     

    图4

      这样就给出了公式,下面贴出三次Beizer曲线的代码,同样可以手动调节参数,大家参考一下。

     

    #include <math.h>
    #include <gl/glut.h>
    #include <iostream>
    using namespace std;
      
    int xCoord[4], yCoord[4];
    int num = 0;
     
    bool finishBeizer = false;
    bool mouseLeftDown = false;
    bool mouseRightDown = false;
     
    /*计算Bezier曲线*/
    void Bezier(int n)
    {
        float f1, f2, f3, f4;
        float deltaT = 1.0 / n;
        float T;
      
        glBegin(GL_LINE_STRIP);
        for (int i = 0; i <= n; i++) {
      
            T = i * deltaT;
      
            f1 = (1-T) *(1- T) * (1-T);
            f2 = 3 * T * (1-T) * (1- T);
            f3 = 3 * T * T * (1-T);
            f4 = T * T * T;
      
            glVertex2f( f1*xCoord[0] + f2*xCoord[1] + f3*xCoord[2] + f4*xCoord[3],
                f1*yCoord[0] + f2*yCoord[1] + f3*yCoord[2] + f4*yCoord[3]);
        }
        glEnd();
    }
      
    /*用鼠标进行绘制,完成后可改变控制点,拖动即可*/
    void display(){
        glClear(GL_COLOR_BUFFER_BIT);
      
        glLineWidth(1.5);
        glColor3f (1.0, 0.0, 0.0);
        glBegin(GL_LINE_STRIP);
        for (int i = 0; i < num; i++)
            glVertex3f (xCoord[i], yCoord[i], 0.0);
        glEnd();
      
        glColor3f (0.0, 0.0, 1.0);
        if (num == 4)
            Bezier(20);
    	
    	glPointSize(10.0f);
    	glBegin(GL_POINTS);
    	glVertex2f(xCoord[0], yCoord[0]);
    	glVertex2f(xCoord[1], yCoord[1]);
    	glVertex2f(xCoord[2], yCoord[2]);
    	glVertex2f(xCoord[3], yCoord[3]);
    	glEnd(); 
    
        glFlush();
        glutSwapBuffers();
    }
      
    void init()
    {
        glClearColor(1.0, 1.0, 1.0, 0.0);
        glShadeModel(GL_FLAT);
    }
      
    void myReshape(int w, int h)
    {
        glViewport(0, 0, (GLsizei)w, (GLsizei)h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluOrtho2D(0.0, (GLsizei)w, (GLsizei)h, 0.0);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    }
      
    void mouse(int button, int state, int x, int y)
    {
        if (!finishBeizer)
        {
            if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
            {
                xCoord[num] = x;
                yCoord[num] = y;
                num++;
     
                if (num == 4)
                    finishBeizer = true;
     
                glutPostRedisplay();
            }
        }
        else
        {
            if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
            {
                mouseLeftDown = true;
            }
     
            if (button == GLUT_LEFT_BUTTON && state == GLUT_UP)
            {
                mouseLeftDown = false;
            }
     
            if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
            {
                mouseRightDown = true;
            }
     
            if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP)
            {
                mouseRightDown = false;
            }
        }
    }
     
    double distance(int x1, int y1, int x2, int y2)
    {
    	return sqrt((x1-x2) * (x1 -x2) + (y1-y2) * (y1-y2));
    }
    
    void motion(int x, int y)
    {
        if (mouseLeftDown)
        {
    		if (distance(xCoord[1], yCoord[1], x, y) < 20)
    		{
    			xCoord[1] = x;
    			yCoord[1] = y;
    		}
    
    		if (distance(xCoord[2], yCoord[2], x, y) < 20)
    		{
    			xCoord[2] = x;
    			yCoord[2] = y;
    		}
        }
     
     
        glutPostRedisplay();
    }
      
    int  main(int argc, char** argv)
    {
        glutInit(&argc, argv);
        glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB );
        glutInitWindowSize (450, 450);
        glutInitWindowPosition (200, 200);
        glutCreateWindow ("hello");
        init ();
      
        glutDisplayFunc(display);
        glutReshapeFunc(myReshape);
        glutMouseFunc(mouse);
        glutMotionFunc(motion);
      
        glutMainLoop();
        return 0;
    }
    

      

  • 相关阅读:
    [POJ 2096] Collecting Bugs
    [POJ 3774] Scout YYF I
    [HDU 4418] Time travel
    [hdu 4586] Play the Dice
    [HDU 4507] 吉哥系列故事――恨7不成妻
    [HDU 4734] F(x)
    [Codeforces] Round #352 (Div. 2)
    刷题向》关于一道像差分约束的数学题BZOJ1045(NORMAL)
    刷题向》关于一道奇怪的贪心(田忌赛马)BZOJ1034(NORMAL-)
    刷题向》关于线段树的区间开根号 BZOJ3211(NORMAL+)
  • 原文地址:https://www.cnblogs.com/caster99/p/4743637.html
Copyright © 2011-2022 走看看