OpenGL曲线函数
生成圆和椭圆等基本曲线的函数并未作为图元功能包含在OpenGL核心库中。但该库包含了显示Bezier样条的功能,该曲线是由一组离散点定义的多项式。OpenGL实用库(GLU)中包含有球面和柱面等三维曲面函数以及生成B样条的函数,它是包含简化Bezier曲线的样条曲线的总集。我们可以使用有理B样条显示圆、椭圆和其他二维曲线。此外,OpenGL实用工具包(GLUT)中还有可以用来显示某些三维曲面(如球面、锥面和其他形体)的函数。然而,所有这些函数比本章中介绍的基本图元应用得更多,因此我们将在第7章进一步讨论这一组函数。
我们还可以使用折线来近似地显示简单曲线。仅需确定一组曲线上的点并将它们连接成一组直线段。折线中的线段越多,曲线越平滑。图3.15给出了用于表示弧的几种折线显示。
第三种可选方法是按下面将给出的算法写出自己的曲线生成函数。首先讨论生成圆和椭圆的高速算法,然后再看一个生成其他二次曲线、多项式和样条曲线的函数。
圆生成算法
由于圆是图形中经常使用的元素,因此在大多数图形软件中都包含生成圆和圆弧的函数。这些软件有时也会提供一个能显示包括圆和椭圆在内的多种曲线的通用函数。
圆的特性
我们将圆定义为所有距中心位置(xc,yc)为给定值r的点集(参见图3.16 )。对于任意的圆点(x,y),这个距离关系可用笛卡儿坐标系中的勾股(Pythagorean)定理定义为
利用这个方程,我们可以沿x轴从xc-r到xc+r以单位步长计算对应的y值,从而得到圆周上每点的位置:
但这并非是生成圆的最好方法。这个方法的一个问题是每一步包含很大的计算量。而且,如图3.17所示,所画像素位置间的间距是不一致的。我们可以在圆斜率的绝对值大于1后,交换x和y(即步进y值并计算x值)来调整间距。但是,这种方法增加了算法所需的计算量和处理过程。
另一种消除图3.17中不等间距的方法是使用极坐标r和θ(参见图3.16)来计算沿圆周的点。
以参数极坐标形式表示圆方程,可以得到方程组:
使用上述方法以固定角度为步长生成显示结果时,就可以利用沿圆周的等距点来绘制出圆。为了减少计算量,我们可以在相邻点间使用较大的角度间隔并用线段连接相邻点来逼近圆的路径。在光栅显示中设定角度间隔为1/r可获得较连续的边界。这样绘出的像素位置大约间隔一个单位。尽管极坐标系统提供了等距点,但三角函数计算是十分耗时的。
对于上述任何一种圆生成算法,考虑圆的对称性可以减少计算量。圆的形状在每个象限中是相似的。因此,如果我们确定了在第一象限中圆的位置,则可以生成该圆在xy平面中第二象限的部分,这是因为两个圆弧段对于y轴是对称的。考虑对于x轴的对称性,根据第一和第二象限中的圆弧可以得到第三和第四象限的圆弧。在八分圆之间也有对称性,因此可以进一步细化,一个象限内的相邻八分圆的圆弧对于分割两个部分的45度直线是对称的。这种对称情况可参见图3.18,图中八分之一圆上的一点(x,y)将映射到xy平面的其他七个八分圆的点。这种方法利用了圆的对称性,仅需计算从x=0到x
= y分段内的点就可得到整个圆的所有像素位置。在这个八分圆中,圆弧斜率绝对值小于或等于1.0 。x = 0时圆的斜率是0,而当x = y时圆的斜率是-1.0。
使用对称性及方程(3.26)或方程(3.28)来确定圆周上的像素位置,仍然需要大量的计算时间。笛卡儿方程(3.26)包括乘法和平方根运算,而参数方程中包含乘法和三角运算。更有效的画圆算法是如同Bresenham画线算法一样以决策参数的增量计算为基础,这样仅仅包括简单的整数处理。
通过设定在每一取样步骤中寻找最接近圆周像素的决策参数,可以将光栅系统的Bresenham画线算法移植为画圆算法。然而,圆方程(3.26)是非线性的,计算像素与圆的距离必须进行平方根运算。Bresenham画圆算法则通过比较像素与圆的距离的平方而避免了平方根运算。
然而,不做平方运算而直接比较距离是可能的。该方法的基本思想是检验两像素间的中间位置以确定该中点是在圆边界之内还是之外。这种方法更易应用于其他圆锥曲线,并且对于整数圆半径,中点方法生成与Bresenham画圆算法相同的像素位置。而且使用中点检验时,沿任何圆锥截面曲线所确定的像素位置,其误差限制在像素间隔的1/2以内。