OpenGL绘制贝塞尔曲线

 更新时间:2020年04月20日 14:58:12   作者:薛昭君  
这篇文章主要为大家详细介绍了OpenGL绘制贝塞尔曲线,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了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个点的贝塞尔曲线,所以数组大小为4
static 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;
}

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

相关文章

  • c语言 字符串的拼接和分割实例

    c语言 字符串的拼接和分割实例

    今天小编就为大家分享一篇c语言 字符串的拼接和分割实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • C/C++整数乘积的溢出问题的解决

    C/C++整数乘积的溢出问题的解决

    整数乘积的溢出问题是指两个整数相乘得到的结果超过了所能表示的数据类型的范围,本文给大家介绍了C/C++整数乘积的溢出问题的解决,需要的朋友可以参考下
    2024-02-02
  • C语言编程中建立和解除内存映射的方法

    C语言编程中建立和解除内存映射的方法

    这篇文章主要介绍了C语言编程中建立和解除内存映射的方法,分别为mmap()函数和munmap()函数的使用,需要的朋友可以参考下
    2015-08-08
  • C++多线程编程超详解

    C++多线程编程超详解

    本文给大家介绍的是C++多线程编程,由于C++本身没有多线程机制,在windows下我们使用调用SDK win32 api来实现,示例都很简单,讲解的也很详细,推荐给大家
    2021-09-09
  • VSCODE调试RDKit内核的方法步骤(C++)

    VSCODE调试RDKit内核的方法步骤(C++)

    本文主要介绍了VSCODE调试RDKit内核的方法步骤,这个过程可以分为三个部分:安装 RDKit 所需环境,安装 VSCode 相应插件, 写调试代码编译,感兴趣的可以了解一下
    2021-08-08
  • C语言实现仓库物资管理系统

    C语言实现仓库物资管理系统

    这篇文章主要为大家详细介绍了C语言实现仓库物资管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • C++流程控制中用于跳转的return和goto语句学习教程

    C++流程控制中用于跳转的return和goto语句学习教程

    这篇文章主要介绍了C++流程控制中用于跳转的return和goto语句学习教程,是C++入门学习中的基础知识,需要的朋友可以参考下
    2016-01-01
  • 用C++的odeint库求解微分方程

    用C++的odeint库求解微分方程

    求解微分方程的数值解一般使用MATLAB等数值计算软件,其实C++也可以求解微分方程,需要用到odeint库,它是boost库的一部分。官方教程和示例比较晦涩,本文力求用较短的篇幅介绍它的基本用法,需要的朋友可以参考下面文章的具体内容
    2021-09-09
  • C++ decltype用法举例说明

    C++ decltype用法举例说明

    decltype是C++11添加的一个新的关键字,目的是选择并返回操作数的数据类型,重要的是,在此过程中编译器分析表达式并得到它的类型,却不实际计算表达式的值,今天通过本文给大家介绍C++ decltype用法,通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2021-07-07
  • C语言高效实现向量循环移位

    C语言高效实现向量循环移位

    这篇文章主要为大家详细介绍了C语言高效实现向量循环移位,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-03-03

最新评论