OpenGl中的Nurbs B样条曲面绘制

时间:2023-03-09 00:31:26
OpenGl中的Nurbs B样条曲面绘制

NURBS

贝塞尔曲线的缺点是当我们增加很多控制点的时候,曲线变得不可控,其连续性会变差差。如果控制点很多(高阶曲线),当我们调整一个控制点的位置,对 整个曲线的影响是很大的。要获得更高级的控制,可以使用GLU库提供的NURBS(非均匀有理B样条)。通过这些函数我们可以在求值器中调整控制点的影响 力,在有大量控制点的情况下,依然可以产生平滑的曲线。

从贝塞尔到B样条

贝塞尔曲线由起点、终点和其他控制点来影响曲线的形状。在二次贝塞尔曲线和三次贝塞尔曲线中,可以通过调整控制点的位置而得到很好的平滑性(C2级 连续性 曲率级)的曲线。当增加更多的控制点的时候,这种平滑性就被破坏了。如下图所示,前两个曲线很平滑(曲率级的连续性),第三个曲线在增加了一个控制点之 后,曲线被拉伸了,其平滑性遭到了破坏。

  OpenGl中的Nurbs B样条曲面绘制

B样条的工作方式类似于贝塞尔曲线,但不同的是曲线被分成很多段。每段曲线的形状只受到最近的四个控制点的影响,这样曲线就像是4阶的贝塞尔曲线拼接起来的。这样很长的有很多控制点的曲线就会有固定的连续性,平滑性(每一段都是c2级的连续性)。

结点

NURBS(非均匀有理B样条)的真正威力在于,可以调整任意一段曲线中的四个控制点的影响力,来产生较好的平滑性。这是通过一系列结点来控制的。每个控制点都定义了两个结点的值。结点的取值范围是u或v的定义域,而且必须是非递减的。

结点的值决定了落在u、v参数定义域内的控制点的影响力。下图的曲线表示控制点对一条在u参数定义域内的具有四个单位的曲线的影响。下图表示中间点对曲线的影响更大,而且只有在[0,3]范围内的控制点才会对曲线产生影响。

OpenGl中的Nurbs B样条曲面绘制

在u、v参数定义域内的控制点对曲线的形状会有有影响,而且我们可以通过结点来控制控制点的影响力。非均匀性就是指一个控制点的影响力的范围是可以改变的。

以下内容及节选自 http://www.rhino3d.com/cn/nurbs

节点 ( Knot ) 是一个 ( 阶数 + N - 1 ) 的数字列表,N 代表控制点数目。有时候这个列表上的数字也称为节点矢量 ( Knot Vector ),这里的矢量并不是指 3D 方向。

节点列表上的数字必须符合几个条件,确定条件是否符合的标准方式是在列表上往下时,数字必需维持不变或变大,而且数字重复的次数不可以比阶数大。例 如,阶数 3 有 15 个控制点的 NURBS 曲线,列表数字为 0,0,0,1,2,2,2,3,7,7,9,9,9 是一个符合条件的节点列表。列表数字为 0,0,0,1,2,2,2,2,7,7,9,9,9 则不符合,因为此列表中有四个 2,而四比阶数大 ( 阶数为 3 )。

节点值重复的次数称为节点的重数 ( Multiplicity ),在上面例子中符合条件的节点列表中,节点值 0 的重数值为三;节点值 1 的重数值为一;节点值 2 的重数为三;节点值 7 的重数值为二;节点值 9 的重数值为三。如果节点值重复的次数和阶数一样,该节点值称为全复节点 ( Full-Multiplicity Knot )。在上面的例子中,节点值 0、2、9 有完整的重数,只出现一次的节点值称为单纯节点 ( Simple Knot ),节点值 1 和 3 为单纯节点。

如果在节点列表中是以全复节点开始,接下来是单纯节点,再以全复节点结束,而且节点值为等差,称为均匀 ( Uniform )。例如,如果阶数为 3 有 7 个控制点的 NURBS 曲线,其节点值为 0,0,0,1,2,3,4,4,4,那么该曲线有均匀的节点。如果节点值是 0,0,0,1,2,5,6,6,6 不是均匀的,称为非均匀 ( Non-Uniform )。在 NURBS 的 NU 代表“非均匀”,意味着在一条 NURBS 曲线中节点可以是非均匀的。

在节点值列表中段有重复节点值的 NURBS 曲线比较不平滑,最不平滑的情形是节点列表中段出现全复节点,代表曲线有锐角。因此,有些设计师喜欢在曲线插入或移除节点,然后调整控制点,使曲线的造型 变得平滑或尖锐。因为节点数等于 ( N + 阶数 - 1 ),N 代表控制点的数量,所以插入一个节点会增加一个控制点,移除一个节点也会减少一个控制点。插入节点时可以不改变 NURBS 曲线的形状,但通常移除节点必定会改变 NURBS 曲线的形状。

节点(Knot)与控制点

控制点和节点是一对一成对的是常见的错误概念,这种情形只发生在 1 阶的 NURBS ( 多重直线 )。较高阶数的 NURBS 的每 ( 2 x 阶数 ) 个节点是一个群组,每 ( 阶数 + 1 ) 个控制点是一个群组。例如,一条 3 阶 7 个控制点的 NURBS 曲线,节点是 0,0,0,1,2,5,8,8,8,前四个控制点是对应至前六个节点;第二至第五个控制点是对应至第二至第七个节点 0,0,1,2,5,8;第三至第六个控制点是对应至第三至第八个节点 0,1,2,5,8,8;最后四个控制点是对应至最后六个节点

创建NURBS表面

GLU库中提供了易用高级的绘制NURBS表面的函数。我们不需要显示地调用求值函数或建立网格。渲染一个NURBS表面的步骤如下:

  1. 创建一个NURBS渲染对象 gluNewNurbsRenderer()
  2. 调用相关的NURBS函数来修改曲线或曲面的外观 gluNurbsProperty
  3. 定义表面,渲染NURBS gluBeginSurface gluNurbsSurface gluEndSurface
  4. 销毁NURBS渲染对象 gluDeleteNurbsRenderer();

我们通过gluNewNurbsRenderer函数来为NURBS创建一个渲染器对象,在最后使用gluDeleteNurbsRenderer销毁它。代码如下:

// NURBS 对象指针 GLUnurbsObj * pNurb = NULL; ... ... // 创建NURBS对象 pNurb = gluNewNurbsRenderer(); ... if (pNurb) gluDeleteNurbsRenderer(pNurb);

NURBS属性

在创建了NURBS渲染器之后,我们需要设置NURBS的属性。

//设置采样容差

gluNurbsProperty(pNurb, GLU_SAMPLING_TOLERANCE, 25.0f);

//填充一个实体的表面

gluNurbsProperty(pNurb, GLU_DISPLAY_MODE, (GLfloat)GLU_FILL);

GLU_SAMPLING_TOLERANCE决定了网格的精细程度。GLU_FILL表示使用填充模式,相应的GLU_OUTLINE_POLYGON是线框模式。

定义表面

表面通过一组控制点和一个结点序列来定义。使用gluNurbsSurface函数来定义表面,这个函数要在gluBeginSurface和gluEndSurface中间:

// 渲染NURB // 开始NURB表面的定义 gluBeginSurface(pNurb); gluNurbsSurface(pNurb, // 指针指向NURBS渲染器 8 , Knots, // u定义域内的结点个数,以及结点序列 8 , Knots, // v定义域内的结点个数,以及结点序列 4 * 3 , // u方向上控制点的间隔 3 , // v方向上控制点的间隔 & ctrlPoints[ 0 ][ 0 ][ 0 ], // 控制点数组 4 , 4 , // u,v 的次数 GL_MAP2_VERTEX_3); // 表面的类型 // 完成定义 gluEndSurface(pNurb);
程序如下:
     float ctrlpoints[][][]={
{{100.0,270.0,0.0},//p00
{105.0,180.0,0.0},//p01
{110.0,160.0,0.0},//p02
{155.0,100.0,0.0}},//p03
{{180.0,200.0,0.0},//p10
{190.0,130.0,0.0},//p11
{200.0,110.0,0.0},//p12
{240.0,70.0,0.0}},//p13
{{310.0,200.0,0.0},//p20
{320.0,130.0,0.0},//p21
{330.0,110.0,0.0},//p22
{370.0,70.0,0.0}},//p23
{{420.0,270.0,0.0},//p30
{430.0,180.0,0.0},//p31
{440.0,160.0,0.0},//p32
{490.0,120.0,1.0}}//p33
}; glPushMatrix();
//绘制控制点与控制线
glScaled(0.2, 0.2, 0.2); glPointSize(4.0f);
glColor3f(0.0, 0.0, 1.0);
glColor3f(, , );
glBegin(GL_POINTS);
for (int i = ; i < ; i++)
{
for (int j = ; j < ; j++)
glVertex3fv(ctrlpoints[i][j]); }
glEnd();
//绘制控制线
glLineWidth(1.5f);
glColor3f(0.0,1.0,1.0);
for (int i = ; i < ; i++)
{
glBegin(GL_LINE_STRIP);
for (int j = ; j < ; j++)
glVertex3fv(ctrlpoints[i][j]);
glEnd(); glBegin(GL_LINE_STRIP);
for (int j = ; j < ; j++)
glVertex3fv(ctrlpoints[j][i]);
glEnd();
}
//绘制B样条控制曲面
GLfloat knots[]={0.0,0.0,0.0,0.0,1.0,1.0,1.0,1.0}; //B样条控制向量
glLineWidth(1.0f);
glColor3f(0.0, 0.0, 0.0); gluNurbsProperty(pNurb,GLU_SAMPLING_TOLERANCE,25.0); //设置属性
gluNurbsProperty(pNurb,GLU_DISPLAY_MODE, GLU_OUTLINE_POLYGON);
gluBeginSurface(pNurb);//开始绘制
gluNurbsSurface(pNurb,
,knots,
,knots,
*,
,
&ctrlpoints[][][],
, ,
GL_MAP2_VERTEX_3); gluEndSurface(pNurb); //结束绘制

for (int j = ; j <= ; j++)
{
glBegin(GL_LINE_STRIP);
for (int i = ; i <= ; i++)
glEvalCoord2f((GLfloat)i/30.0, (GLfloat)j/8.0);
glEnd();
glBegin(GL_LINE_STRIP);
for (int i = ; i <= ; i++)
glEvalCoord2f((GLfloat)j/8.0, (GLfloat)i/30.0);
glEnd();
}
glPopMatrix();

  程序运行效果如下:

  aaarticlea/png;base64,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" alt="" />