原理

三次bezier曲线函数 python_三次bezier曲线函数 python

reshape函数细节

原文链接:

改变窗口形状,所绘制的物体不变形,而只是大小发生变化
void reshape (int w, int h)
{
glviewport (0, 0, (glsizei) w, (glsizei) h);
glmatrixmode (gl_projection);
glloadidentity ();
if (w <= h)
gluortho2d (0.0, 30.0, 0.0, 30.0 * (glfloat) h/(glfloat) w);
else
gluortho2d (0.0, 30.0 * (glfloat) w/(glfloat) h, 0.0, 30.0);
glmatrixmode(gl_modelview);
}
看这个reshape函数当窗口发生变化,窗口的w(宽度)和h(高度)参数传给reshape函数,
glviewport (0, 0, (glsizei) w, (glsizei) h);
把视口设置为铺满整个窗口, if (w <= h)
gluortho2d (0.0, 30.0, 0.0, 30.0 * (glfloat) h/(glfloat) w);
else
gluortho2d (0.0, 30.0 * (glfloat) w/(glfloat) h, 0.0, 30.0);
把投影得到的视景体按照视口变化的比例变化视景体的比例;简单地说,本来视景体宽高比是1:1,视口宽高比也是1:1,这时绘制了一个物体。然后因为窗口发生变化,视口也变化,假如变成了2:1;这时如果用1:1的视景体放到2:1的视口上肯定会变形,所以要把视景体变成2:1,这样,虽然物体看起来变大(或变小)了,但长宽比例不变,也就看起来不变形了。注意这个参数(glfloat) w/(glfloat) h。
原文链接:

 

glMatrixMode()函数

这两个都是glMatrixMode()函数的参数,那就先说说glMatrixMode吧~,这个函数其实就是对接下来要做什么进行一下声明,也就是在要做下一步之前告诉计算机我要对“什么”进行操作了,这个“什么”在glMatrixMode的“()”里的选项(参数)有,GL_PROJECTION,GL_MODELVIEW和GL_TEXTURE;

如果参数是GL_PROJECTION,这个是投影的意思,就是要对投影相关进行操作,也就是把物体投影到一个平面上,就像我们照相一样,把3维物体投到2维的平面上。这样,接下来的语句可以是跟透视相关的函数,比如glFrustum()或gluPerspective();
如果参数是GL_MODELVIEW,这个是对模型视景的操作,接下来的语句描绘一个以模型为基础的适应,这样来设置参数,接下来用到的就是像gluLookAt()这样的函数;
若是GL_TEXTURE,就是对纹理相关进行操作;
顺便说下,OpenGL里面的操作,很多是基于对矩阵的操作的,比如位移,旋转,缩放,所以,这里其实说的规范一点就是glMatrixMode是用来指定哪一个矩阵是当前矩阵,而它的参数代表要操作的目标,GL_PROJECTION是对投影矩阵操作,GL_MODELVIEW是对模型视景矩阵操作,GL_TEXTURE是对纹理矩阵进行随后的操作

OpenGL常用函数介绍

需要包含头文件#include<GL/glut.h>,这是GLUT的头文件。

注意main函数中的各语句,除了最后的return之外,其余全部以glut开头。这种以glut开头的函数都是GLUT工具包所提供的函数,下面对用到的几个函数进行介绍。
1、glutInit,对GLUT进行初始化。其格式比较死板,照抄glutInit(&argc, argv)就可以。
2、glutInitDisplayMode,设置显示方式,其中GLUT_RGB表示使用RGB颜色,与之对应的还有GLUT_INDEX(表示使用索引颜色)。GLUT_SINGLE表示使用单缓冲,与之对应的还有GLUT_DOUBLE(使用双缓冲)。
3、glutInitWindowPosition,设置窗口在屏幕中的位置。
4、glutInitWindowSize,设置窗口的大小。
5、glutCreateWindow,创建窗口。参数将被作为窗口的标题。注意:窗口被创建后,并不立即显示到屏幕上,需要调用glutMainLoop才能看到窗口。
6、glutDisplayFunc,设置一个函数,当需要进行画图时,这个函数就会被调用。
7、glutMainLoop,进行一个消息循环。

以gl开头的函数都是OpenGL的标准函数。
1、glClear,清除。
2、glBeginglEnd是一对,中间写的是要画的内容。
3、glFlush,保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待)。
原文链接:

OpenGL框架实现

 

窗口初始化

glutInit(&argc, argv); // 初始化glut窗口
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // 设定显示窗口的缓存和颜色模型
glutInitWindowPosition(50, 100); // 决定窗口左上角离屏幕左上角的位置
glutInitWindowSize(400, 300); // 设定窗口大小
glutCreateWindow("The Hello World Window!"); // 窗口名

glutInit(int *argc, char **argv);

glut初始化API
void glutInit(int *argc, char *argv);
这个函数用来初始化 GLUT 库.这个函数从 main 函数获取其两个参数.对应main 函数的形式应是:int main(int argc,char
argv[]);

在这个部分我们将在我们的程序里建立一个main函数,这个main函数将完成必须的初始化和开启事件处理循环。所有的GLUT函数都有glut前缀并且那些完成一些初始化的函数有glutInit前缀。你首先要做的是调用函数glutInit()。

Void glutInit(int*argc,char**argv);

参数:

Argc:一个指针,指向从main()函数传递过来的没更改的argc变量。

Argv:一个指针,指向从main()函数传递过来的没更改的argv变量。

用GetSystemMetrics获取屏幕的宽度和高度
int x, y;
x = GetSystemMetrics(SM_CXSCREEN); //屏幕宽度
y = GetSystemMetrics(SM_CYSCREEN); //屏幕高度

glClearColor,glShadeModel

glClearColor ( )

就是用来设置这个 “ 底色 ” 的,即所谓的背景颜色。glClearColor ( ) 只起到Set 的作用,并不Clear 任何。

void glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
//红、绿、蓝和 alpha 值,指定值范围均为[ 0.0f,1.0f ]

glShadeModel ( )

函数用于控制 opengl 中绘制指定两点间其他点颜色的过渡模式。

参数一般为 GL_SMOOLH ( 默认 ) 或 GL_FLAT。

如果两点的颜色相同,则使用这两个参数效果相同;

如果两点颜色不同,GL_SMOOLH 会出现过渡效果; GL_FLAT 则以指定的某一点的单一色绘制其他所有点

原文链接

鼠标交互

要将鼠标有关的数据发送给应用程序,则需要将鼠标事件注册到glutMouseFunc(myMouse)。其中myMouse(int button, int state, int x,int y);
函数名可以自己制定,在回调函数glutMouseFunc()中替换成相应的函数头就好。
但是其中的四个参数是不可缺少的:
button:GLUT_LEFT_BUTTON,GLUT_MIDDLE_BUTTON,GLUT_RIGHT_BUTTON,分别指代鼠标左键,中间键(鼠标滚轮),右键;
state:鼠标的状态GLUT_UP,GLUT_DOWN;
x和y指明鼠标在窗口中的位置(x为鼠标距离窗口左边的像素数,y为鼠标距离窗口顶端的像素数,在计算是为(x,screenLength-y)。)

原文链接

glutpostredisplay,mianloop用法理解

glutPostRedisplay 标记当前窗口需要重新绘制。通过glutMainLoop下一次循环时,窗口显示将被回调以重新显示窗口的正常面板。多次调用glutPostRedisplay,在下一个显示回调只产生单一的重新显示回调。
为了便于理解,用下面的例子来说明:
  假设有绘制代码:
 

glutDisplayFunc(display); // opengl drawing goes here
   glutTimerFunc(30, drive, -1); // physics, movement equations here
   glutMainLoop();
   另外有代码如下:
   void drive (int data)
   {
   glutTimerFunc(30, drive, -1);// call drive() again in 30 milliseconds
    /callback function moves the car. … move x, y, z, etc
   前面的代码不用理解,就是移动了物体,绘制的画面改变了/
   glutPostRedisplay();
   }
   如果有glutpostredisplay,mianloop运行的过程会像下面这样:
   drive (-1);
   display();
   drive (-1);
   display();
   drive (-1);
   display();
   …
   如果没有glutpostredisplay,mianloop运行的过程会像下面这样:
   drive (-1);
   drive (-1);
   drive (-1);


  …

Bezier部分代码解释

三次bezier曲线函数 python_#include_02

3次Beizer曲线绘制代码

#include<glut.h>
#include<math.h>
#include<windows.h>
#include<vector>
#include<algorithm>
#include<iostream>
using namespace std;
#define N 1000  //绘制Bezier曲线的点数设置为1000

struct Point
{
    int x, y;
    Point(){};
    Point(int tx, int ty)
    {
        x = tx;
        y = ty;
    }
};
vector<Point> p;//下标从0开始

double getRatio(double t,double a,double b,double c,double d)
{
    return a * pow(t, 3) + b * pow(t, 2) + c * t + d;
}

void Bezier()
//画Bezier曲线
{
    double derta = 1.0 / N;
    glPointSize(2);//设置点的大小为2
    glColor3d(0, 0, 1);//设置Bezier曲线(点)颜色为蓝 RGB(0,0,255)
    glBegin(GL_POINTS);//开始画点
    for (int i = 1; i <= N; i++)
    {
        double t = derta * i;
        double ratio[4];
        ratio[0] = getRatio(t, -1, 3, -3, 1);
        ratio[1] = getRatio(t, 3, -6, 3, 0);
        ratio[2] = getRatio(t, -3, 3, 0, 0);
        ratio[3] = getRatio(t, 1, 0, 0, 0);
        double x=0, y=0;
        for (int j = 0; j < 4; j++)
        {
            x += ratio[j] * p[j].x;
            y += ratio[j] * p[j].y;
        }
        glVertex2d(x, y);//画点
    }
    glEnd();//结束画点
}
void myDisplay()
//画鼠标 自选点和折线
{
    glClear(GL_COLOR_BUFFER_BIT);    //清除颜色缓存和深度缓存

    //画点
    glPointSize(5);
    glColor3d(1, 0, 0);//设置颜色为红 RGB(255,0,0)
    glBegin(GL_POINTS);
    for (int i = 0; i < p.size(); i++)
        glVertex2d(p[i].x, p[i].y);
    glEnd();

    //画线
    glLineWidth(2);//设置线的宽度为2
    glColor3d(0, 0, 0);//设置线段颜色为黑色
    glBegin(GL_LINE_STRIP); //开始画线
    for (int m = 0; m < p.size(); m++)//这里防止i变量重复定义,把变量改为m
        glVertex2d(p[m].x, p[m].y);
    glEnd();//结束画线

    if (p.size() == 4)//已经选了4个点了,开始画Bezier曲线
        Bezier();

    glFlush();//清空缓冲区,将指令送往缓硬件立即执行
}
void mouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN && p.size() < 4)//按下左键,且次数小于4次
    {
        Point t(x, y);	
        p.push_back(t);	//记录鼠标按下位置
        glutPostRedisplay();//标记当前窗口需要重新绘制
    }
}

void Reshape(int w, int h)      //当窗口发生变化,窗口的w(宽度)和h(高度)参数传给reshape函数,
{
    glViewport(0, 0, w, h);		//width,height  指定视口矩形的宽度和高度.
    glMatrixMode(GL_PROJECTION);//指定哪一个矩阵是当前矩阵,GL_PROJECTION是对投影矩阵操作
    glLoadIdentity();			//重置当前指定的矩阵为单位矩阵。
    gluOrtho2D(0, w, h, 0);		//将当前的可视空间设置为正投影空间。
    glMatrixMode(GL_MODELVIEW);	//GL_MODELVIEW是对模型视景矩阵操作
    glLoadIdentity();
}

void initWindow(int &argc, char *argv[], int width, int height, char *title)    //初始化并显示到屏幕中央
{
    glutInit(&argc, argv);		// 初始化glut窗口
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);		// 设定显示窗口的缓存和颜色模型
    glutInitWindowPosition((GetSystemMetrics(SM_CXSCREEN) - width) >> 1, (GetSystemMetrics(SM_CYSCREEN) - height) >> 1); 
	//GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN)是获取显示设备的分辨率,分别为屏幕宽度,屏幕高度
	// 决定窗口左上角离屏幕左上角的位置
    glutInitWindowSize(width, height);       //指定窗口大小
    glutCreateWindow(title);				// 窗口名
 
    glClearColor(1, 1, 1, 0);				//设置背景色为白色
    glShadeModel(GL_FLAT);		//设置指定两点间其他点颜色的过渡模式。GL_FLAT以指定的某一点的单一色绘制其他所有点
}

int main(int argc, char *argv[])
{
    initWindow(argc, argv, 600, 600, "三次Bezier曲线");

    puts("\n\t用鼠标在窗口选择四个点来绘制三次Bezier曲线");

    glutDisplayFunc(myDisplay);
    glutReshapeFunc(Reshape);
    glutMouseFunc(mouse);

    glutMainLoop();

    return 0;
}