【转】贝塞尔曲线和曲面

三次贝塞尔曲面 三次贝尔赛曲面 基于DirectX11的曲面细分章节实现的矩形的三次贝塞尔曲面,特此做下笔记 一个矩阵,可以分为水平方向垂直方向,分别做贝塞尔曲线。 一个4*4控制点的面片,第i行的贝塞尔曲线函数 通过对每一行的贝塞尔曲线的基础上,对同一列做列贝塞尔曲线,其中控制点p是行贝塞尔曲线的坐标; 将所有列曲线上的顶点求出后,求得到了贝塞尔曲面。 由于并没有新的控制点... 阅读详情

【转】贝塞尔曲线和曲面

原文地址:http://my.oschina.net/sweetdark/blog/183721
参数方程表现形式

在中学的时候,我们都学习过直线的参数方程:y = kx + b;其中k表示斜率,b表示截距(即与y轴的交点坐标)。类似地,我们也可以用一个参数方程来表示一条曲线。1962年,法国工程师贝塞尔发明了贝塞尔曲线方程。关于贝塞尔曲线的详细介绍可以参考(维基贝塞尔)。这里只介绍OpenGL实现贝塞尔的函数。

OpenGl定义一条曲线时,也把它定义为一个曲线方程。我们把这条曲线的参数成为u,它的值域就是曲线的定义域。曲面则需要u和v两个参数来描述。注意,u和v参数只表示了描述曲线的参数方程的范围,它们并没有反映实际的坐标值。其坐标可以表示为:

x = f(u); y = g(u); z = h(u);

如下图:

image

控制点

贝塞尔曲线的形状由控制点来控制。贝塞尔曲线的控制点个数为曲线的阶。根据控制点的个数,贝塞尔曲线又分为二次贝塞尔曲线,三次贝塞尔曲线,高阶贝塞尔曲线。

image

线性曲线

Image(1)

线性贝塞尔曲线演示动画,t in [0,1]

二次方曲线

为建构二次贝塞尔曲线,可以中介点Q0Q1作为由0至1的t

  • P0P1的连续点Q0,描述一条线性贝塞尔曲线。

  • P1P2的连续点Q1,描述一条线性贝塞尔曲线。

  • Q0Q1的连续点Bt),描述一条二次贝塞尔曲线。

Image(1)
Image(2)

二次贝塞尔曲线的结构
二次贝塞尔曲线演示动画,t in [0,1]

三次方曲线

为建构高阶曲线,便需要相应更多的中介点。对于三次曲线,可由线性贝塞尔曲线描述的中介点Q0Q1Q2,和由二次曲线描述的点R0R1所建构:

Image(2)
Image(3)

三次贝塞尔曲线的结构
三次贝塞尔曲线演示动画,t in [0,1]

连续性

两段曲线是否相连接,代表这两段曲线是否连续的。曲线的连续性分为4种,无连续,点连续,正切连续,曲率连续。下图分别表示了这几种情况:

image

其中曲率连续的曲线过渡的更平滑。我们可以通过参数来设置曲线的连续性。

求值器

OpenGL提供了一些函数来绘制贝塞尔曲线和曲面。我们只需要提供控制点和u,v作为参数,然后调用求值函数来绘制曲线。

2D曲线的例子:

//控制点 GLint numOfPoints = 4; static GLfloat controlPoints[4][3] = {{-4.0f, 0.0f, 0.0f},
{-6.0f, 4.0f, 0.0f},
{6.0f, -4.0f, 0.0f},
{4.0f, 0.0f, 0.0f}}; void SetupRC()
{
  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  glColor3f(1.0f, 0.0f, 1.0f);
} 
//画控制点
void DrawPoints()
{
  glPointSize(2.5f);
  glBegin(GL_POINTS); for (int i = 0; i < numOfPoints; ++i)
    {
      glVertex3fv(controlPoints[i]);
    }
  glEnd();
} 

void ChangeSize(GLsizei w, GLsizei h)
{
  if (h == 0)
  {
    h = 1;
  }

  glViewport(0, 0, w, h);
   //使用正交投影
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();

  gluOrtho2D(-10.0f, 10.0f, -10.0f, 10.0f);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
} 

void RenderScene()
{
  glClear(GL_COLOR_BUFFER_BIT);
   //设置贝塞尔曲线,这个函数其实只需要调用一次,可以放在SetupRC中设置
    glMap1f(GL_MAP1_VERTEX_3, //生成的数据类型
     0.0f, //u值的下界
      100.0f, //u值的上界
       3, //顶点在数据中的间隔,x,y,z所以间隔是3
        numOfPoints, //u方向上的阶,即控制点的个数
         &controlPoints[0][0] //指向控制点数据的指针 );
   //必须在绘制顶点之前开启
   glEnable(GL_MAP1_VERTEX_3);
    //使用画线的方式来连接点
   glBegin(GL_LINE_STRIP);
  for (int i = 0; i <= 100; i++)
  {
    glEvalCoord1f((GLfloat)i);
  }
  glEnd();

  DrawPoints();

  glutSwapBuffers();

}

image

在RenderScene函数中调用glMap1f来为曲线创建映射。第一个参数为GL_MAP1_VERTEX3,设置求值器产生顶点为三元组(x,y,z).还可以设置为产生纹理坐标和颜色信息。参考glMap1.后面的两个参数设定了u的取值范围[0,100],第四个参数指定了顶点在数组中的间隔,由于顶点是由3个浮点数组成,所以间隔是3.第五个参数指定了控制点的个数,最后一个参数是控制点数组。然后我们需要启用求值器,调用如下:

glEnable(GL_MAP1_VERTEX3);

glEvalCoord1f函数,接受一个参数为曲线的参数值。调用这个函数会通过求值函数求出顶点坐标值,然后内部调用了glVertex。这里使用连线的方式来连接这些顶点:

glBegin(GL_LINE_STRIP);

for(i = 0; I <= 100; i++)

{

  glEvalCoord1f((GLfloat)i);

}

glEnd();

计算曲线

OpenGl还提供了更简单的方式来完成上面的任务。我们可以通过glMapGrid函数来设置一个网格,来告诉OpenGL在u的值域的范围内创建一个包含各个点的空间对称的网格。然后,我们调用glEvalMesh,使用指定的图元(GL_LINE或GL_POINTS)来链接各个点。

我们用下面的两个函数调用

  glMapGrid1f(100, 0.0f, 100.0f);

  glEvalMesh1(GL_LINE, 0, 100);

可以替换下面的代码

glBegin(GL_LINE_STRIP); 
for (int i = 0; i <= 100; i++)
  {
    glEvalCoord1f((GLfloat)i);
  }
glEnd();

使用这种方式更为紧凑。

3D表面

创建一个贝塞尔曲面与创建一个贝塞尔曲线类似。除了给出u的定义域之外,还要给出v的定义域。下面的例子是创建一个贝塞尔曲面。与之前不同的是,我们沿着v的定义域定义了3组控制点。为了保持曲面的简单,这几组控制点只是z值不同。用这种方式画的曲面,看起来像是曲线沿z轴的扩展。

//控制点  GLint nNumPoints = 3;

GLfloat ctrlPoints[3][3][3]= {{{  -4.0f, 0.0f, 4.0f},    
{ -2.0f, 4.0f, 4.0f},    
{  4.0f, 0.0f, 4.0f }},

{{  -4.0f, 0.0f, 0.0f},    
{ -2.0f, 4.0f, 0.0f},    
{  4.0f, 0.0f, 0.0f }},

{{  -4.0f, 0.0f, -4.0f},    
{ -2.0f, 4.0f, -4.0f},    
{  4.0f, 0.0f, -4.0f }}}; //画控制点  void DrawPoints(void)
{ int i,j;    

  glColor3f(1.0f, 0.0f, 0.0f); //把点放大一点,看得更清楚  glPointSize(5.0f);

  glBegin(GL_POINTS); 
  for(i = 0; i < nNumPoints; i++)
   for(j = 0; j < 3; j++)
      glVertex3fv(ctrlPoints[i][j]);
  glEnd();
} 
void RenderScene(void)
{ 
// Clear the window with current clearing color 
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   // 保存模型视图矩阵  
   glMatrixMode(GL_MODELVIEW);
  glPushMatrix(); 
  //旋转一定的角度方便观察  
  glRotatef(45.0f, 0.0f, 1.0f, 0.0f);
  glRotatef(60.0f, 1.0f, 0.0f, 0.0f);


  glColor3f(0.0f, 0.0f, 1.0f); //设置映射方式,只需要设置一次可以在SetupRC中调用。  
  glMap2f(GL_MAP2_VERTEX_3, //生成的数据类型  
  0.0f, // u的下界 
  10.0f, //u的上界  
  3, //数据中点的间隔  
  3, //u方向上的阶  
  0.0f, //v的下界  
  10.0f, //v的上界  
  9, // 控制点之间的间隔  
  3, // v方向上的阶  
  &ctrlPoints[0][0][0]); //控制点数组 
  //启用求值器  
  glEnable(GL_MAP2_VERTEX_3); 
  //从0到10映射一个包含10个点的网格  
  glMapGrid2f(10,0.0f,10.0f,10,0.0f,10.0f); 
  // 计算网格  
  glEvalMesh2(GL_LINE,0,10,0,10); 
  //画控制点  
  DrawPoints();
  
  glPopMatrix();

  glutSwapBuffers();
}

在这里我们用glMap2f替换了之前的glMap1f, 这个函数指定了u和v两个域上的点。除了指定u的上界和下界之外,还要指定v的上界和下界。v定义域内点的距离是9,因为这里使用了3维数组,包含了3个u值,每个u值又包含了3个点,3x3=9。然后指定v方向上的阶,即每个u分支上v方向有多少个点。最后一个参数是指向控制点的指针。

然后我们设置求值器.

//启用求值器

glEnable(GL_MAP2_VERTEX_3);
//从0到10映射一个包含10个点的网格

glMapGrid2f(10,0.0f,10.0f,10,0.0f,10.0f);

计算网格网格表面,用线的方式表示。

// 计算网格
  glEvalMesh2(GL_LINE,0,10,0,10);

image

光照和法线

求值器还可以帮我们生成表面的法线,只需简单的修改一些代码:

把glEvalMesh2(GL_LINE, 0, 10, 0, 10);替换为glEvalMesh2(GL_FILL, 0, 10, 0, 10);然后在初始化时 SetupRC中调用glEnable(GL_AUTO_NORMAL);就可以得到一个收到光照的曲面了。

image


【Qt OpenGL教程】28:贝塞尔曲面 这次教程中,我们将介绍贝塞尔曲面,因此这是关于数学运算的一课(这导致很不好讲),来吧,相信你能搞定它的!这一课中,我们并不是要做一个完整的贝塞尔曲面库(库的话OpenGL已经完成了),而是一个展示概念的程序,来让你熟悉曲面是怎么计算实现的。 阅读详情

相关推荐

实战技术!OpenGL超级宝典笔记——贝塞尔曲线曲面

个人博客导航页(点击右侧链接即可打开个人博客):大牛带你入门技术栈 参数方程表现形式 在中学的时候,我们都学习过直线的参数方程:y = kx + b;其中k表示斜率,b表示截距(即与y轴的交点坐标)。类似地,我们也可以用一个参数方程来表示一条曲线。1962年,法国工程师贝塞尔发明了贝塞尔曲线方程。关于贝塞尔曲线的详细介绍可以参考(维基贝塞尔)。这里只介绍OpenGL实现贝塞尔的函数。 ...

weixin_41663412的博客 1202

基于OpenGL的Loop网格细分

基于OpenGL的Loop网格细分,有算法实现源码试例obj文件

贝塞尔曲线曲面原理

给出一系列点(一般称为控制点),贝塞尔曲线可以利用这些点得到一个平滑的曲线贝塞尔曲线不是一个表达式,而是由一系列离散的点构成的(类似移动最小二乘法)。先由控制点得到的贝塞尔曲线的点P,对点P再进行贝塞尔曲线就得到了贝塞尔曲面。这种方法通过线性插值进行递归的方法求得贝塞尔曲线上的点。

xinxiangwangzhi_的博客 717

opengl实现bezier曲面的纹理贴图、鼠标交互与光照

此程序使用Opengl绘制了带6个纹理的立方体(立方体的每个面用bezier曲面表示),实现了键盘鼠标控制,其中键盘控制如下: L :控制光照光照 ←:向左旋速度增加 →:向右旋速度增加 ↑:向上旋速度增加 ↓:向下旋速度增加 PgUp:立方体向屏幕里移动(离观察者越来越远) PgUp: 立方体向屏幕外移动(离观察者越来越近) 鼠标控制如下: 右键:控制光照 左键:按下左键时可以进行立方体的拖拽使之旋

OpenGL实现贝塞尔曲线曲面

本文实例为大家分享了OpenGL实现贝塞尔曲线曲面的具体代码,供大家参考,具体内容如下 理论基础 贝塞尔曲线曲面OpenGL只能直接绘制基本图元,对于曲线曲面我们一般采用一系列线段或多边形来模拟的,这样当线段或多边形增多时必定很耗性能。其实对于这种曲线曲面,我们可以使用一些控制点,通过求值器程序先计算出坐标等信息,然后直接用这些数据绘制,这样不仅节省内存,还提高了模拟曲线曲面的精度(本质还是通过线段或多边形绘制的,只是求值器提前算出了曲线曲面的顶点信息)。 求值器使用一般步骤:1.启用求值器 2.定义求值器 3.执行求值器。 注释:OpenGl3.1后,本节内容都已经废弃了,这些

贝塞尔曲线-曲线拟合

如下图所示: 在二维平面内选三个不同的点(起点A,中间点B,终点C)并依次用线段连接 在线段ABBC上按比例分割找到新的起点中间点:D、E两点,使得AD/AB=BE/BC 连接DE,并在DE上找到新的起点F点,EC上找到新的中间点G点,使其满足DF/DE=EG/EC 重复步骤1、2、3,找出符合上述条件的所有点,直到新的起点终点C重合或者中间点终点C重合时结束递归 代码如下: class Bezier: def __init__(self,points,baseRatio

轩逸云的博客 5520

OpenGL超级宝典笔记——贝塞尔曲线曲面

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34087503的博客 951

java3d bezier曲面_OpenGL超级宝典笔记——贝塞尔曲线曲面

参数方程表现形式在中学的时候,我们都学习过直线的参数方程:y = kx + b;其中k表示斜率,b表示截距(即与y轴的交点坐标)。类似地,我们也可以用一个参数方程来表示一条曲线。1962年,法国工程师贝塞尔发明了贝塞尔曲线方程。关于贝塞尔曲线的详细介绍可以参考(维基贝塞尔)。这里只介绍OpenGL实现贝塞尔的函数。OpenGl定义一条曲线时,也把它定义为一个曲线方程。我们把这条曲线的参数成为u,它...

weixin_28862113的博客 613

OpenGL超级宝典笔记——贝塞尔曲线曲面

http://my.oschina.net/sweetdark/blog/183721 参数方程表现形式 在中学的时候,我们都学习过直线的参数方程:y = kx + b;其中k表示斜率,b表示截距(即与y轴的交点坐标)。类似地,我们也可以用一个参数方程来表示一条曲线。1962年,法国工程师贝塞尔发明了贝塞尔曲线方程。关于贝塞尔曲线的详细介绍可以参考(维基贝塞尔)。这里只介绍OpenGL实现贝塞...

weixin_30319097的博客 175

计算机图形学十:几何2—贝塞尔曲线(Bézier Curves)与贝塞尔曲面(Bézier Surfaces)

贝塞尔曲线贝塞尔曲面1 贝塞尔曲线(Bézier Curves)2 贝塞尔曲面(Bézier Surfaces)Reference 1 贝塞尔曲线(Bézier Curves) 在进入具体原理讲解之前,首先看一下一条实际的贝塞尔曲线长什么样子 其中 p0,p1,p2,p3p_0,p_1,p_2,p_3p0​,p1​,p2​,p3​为控制点,蓝色所表示曲线正是非常著名的贝塞尔曲线了,可以从图中观察到,曲线会与初始与终止端点相切,并且经过起点p0p_0p0​与终点p3p_3p3​。那么这样一条曲线究竟是怎么

吃人的博客 9461

贝塞尔曲线贝塞尔曲面

本文介绍了贝塞尔曲线曲面的基本原理。贝塞尔曲线通过控制点参数t的线性插值递归生成,n个控制点形成n-1次曲线,具有经过端点、与端点相切、仿射变换凸包等性质。高阶贝塞尔曲线存在局部控制困难的问题,常用分段三次曲线拼接解决。贝塞尔曲面则扩展至三维,通过在u、v两个参数方向上分别进行插值计算生成。文章还简要提及B样条曲线NURBS曲线的特点,它们能更好地实现局部控制描述圆锥曲线贝塞尔曲线广泛应用于图形设计、字体等领域。

人无远虑,必有近忧 4563

基于OpenGL的B样条曲线曲面的绘制

基于OpenGL的B样条曲线曲面的绘制算法,包含了均匀、准均匀、Bezier、各种非均匀B样条曲线曲面的绘制,阶次的升降,以及曲面的光照纹理映射算法。

OPEN GL 关于纹理映射 纹理贴图 贝塞尔曲面的例子

方向键可以进行移动,按F键更改纹理,按B键添加光照。 立方体上面的是贝塞尔曲面,可以通过A键D键进行旋,还可以通过WS键进行变换曲面的扭曲程度。按空格键可以时曲面的轮廓消失。 最里边是一个变幻的圆环 。 .exe文件可以直接执行

OpenGL绘制三次Bezier曲线

主要为大家详细介绍了OpenGL绘制三次Bezier曲线,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

贝塞尔曲线曲面原理及推导过程

③逼近:先给定由若干个型值点勾画的一条折线轮廓,然后要求用曲线曲面逼近这个折线轮廓,折一折线轮廓构成的多边形称为控制多边形。①插值:用光滑的曲线曲面把给定的若干个离散点连接起来,即由型值点构造的曲线曲面通过所有的型值点;显式或隐式方法可以非常直观的表示初等解析曲线曲面曲线曲面的特性也可以通过表示形式清楚的表现出来。⑥规格化的参数变量t∈[0,1],使其相应的几何分量是有界的,而不必用另外的参数去定义边界;由上图可知,当组合的曲线达到2阶连续性的时候,曲线之间就已经有了非常好的光滑连接。

2301_78882629的博客 2007

浅谈贝塞尔曲线

浅谈贝塞尔曲线 前段时间做了一个手写板功能的东西,其中手写部分用二次贝塞尔曲线完成,今天就来总结一下贝塞尔曲线在Android中的应用,先简单介绍各阶贝塞尔曲线的原理,然后实现通过贝塞尔曲线实现波浪线功能,感兴趣的同学继续看下去吧! 概念 在数学的数值分析领域中,贝塞尔曲线(英语:Bézier curve,亦作“贝塞尔”)是计算机图形学中相当重要的参数曲线。更高维度的广泛化贝塞尔曲线就称作贝兹曲面...

子墨博客 4031

贝塞尔曲线基础

贝塞尔曲线于1962年由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由Paul de Casteljau于1959年运用de Casteljau演算法开发,以稳定数值的方法求出贝兹曲线

YiYeZhiNian的博客 2015
上一篇: 【Qt OpenGL教程】28:贝塞尔曲面
下一篇: 【Qt OpenGL教程】29:Blitter函数
cly116
博客等级 码龄12年 290粉丝 33原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值