目录
用于图形应用的通用软件包称为计算机图形应用编程接口(CG API),它提供在C++等程序语言中用来创建图形的函数库。
图形软件包中用来描述各种几何图形元素的函数称为图形输出元语,或简称为图元。
描述对象几何要素的输出图元一般称为几何图元。
坐标系统
为了描述图形,必须确定一个称为世界坐标系的合适的二维或三维笛卡尔坐标系。接着通过给出世界坐标系中的位置等几何描述来定义图形中的对象。
坐标范围:对象坐标x,y,z的最小值和最大值,也成为对象包围盒
屏幕坐标
视频监视器上的位置使用与帧缓存中的像素位置相对应的整数屏幕坐标进行描述。像素的坐标值给出扫描行号(y值)和列号(x值)。屏幕刷新等硬件处理一般从屏幕的左上角开始对像素进行编址。从上到下0到ymax,从左到右0到xmax进行编号。但是,可以使用软件命令行按照任何方式设定屏幕位置的参考系统。
图元的扫描算法使用定义的坐标描述来确定要显示的位置。目前假设每一整数屏幕位置代表像素区域的中心。
setPixel(x,y);将当前颜色设定值存入帧缓存的整数坐标位置(x, y)处
getPixel(x,y, color);color得到一个与存储在位置(x,y)的像素中的颜色值
对于三维图形来说,还需要深度值来存储屏幕坐标信息
绝对和相对坐标描述
绝对坐标:表示指定的值是所在坐标系统中的实时位置
相对坐标:相对于上一次的当前位置的位移量来指定坐标位置
OpenGL中之中指定二维世界坐标系统
OpenGL画点函数
glVertex的后缀可用于2、3、4表示其坐标位置的维数。
glVertex函数的第二个后缀描述坐标数值的具体类型。i(整数)、s(短整数)、f(浮点数)、d(双精度浮点数)
最后,glVertex可以使用显式的坐标值或引入矩阵形式坐标位置的单个变量。如果使用矩阵形式坐标位置,则需要第三个后缀码:v(“向量”)。例如:
OpenGL画线函数
使用图元变量GL_LINES可连接每一对相邻端点而得到一组直线段。OpenGL仅在线段共享一个顶点时承认其相连。
使用GL_LINE_STRIP可以获得折线。显示第一个端点到最后一个端点之间一组首尾相连的线段。
使用GL_LINE_LOOP生成封闭折线。主要的线段和生成折线一样画出,但是增加了一条直线段,将最后一个端点和第一个端点相连接。
OpenGL曲线函数
OpenGL核心库中并未包含生成圆和椭圆等基本曲线的函数,仅包含了显示Bezier样条的功能,该曲线是由一组离散点定义的多项式。
OpenGL实用库(GLU)中包含有球面和柱面等三维曲线生成有理B样条的函数,它是包含简化Bezier曲线的样条曲线的总集。
Open实用工具包(GLUT)中还有可以用来显示某些三维曲面(如球面、锥面和其他形体)的函数。
填充区图元
除了点、直线段和曲线之外,另外有一种有用的描述图形组成部分的结构是使用某种颜色或图案进行填充的区域。这种类型的图形部分一般称为填充区或填充的区域。
图4.6给出了几种可能的填充区形状。
尽管有可能使用各种形状,但图形库一般不支持任意填充形状的描述。多数库函数要求填充区指定为多边形。
使用一组多边形面片描述的对象称为标准图形对象或称为图形对象。
多边形填充区
一个多边形在数学上定义为由三个或更多称为顶点的坐标位置描述的平面图形,这些顶点由称为多边形的边顺序连接。一个多边形的所有顶点必须在同一个平面上且所有的边之间无交叉。把术语“多边形”限定为那些有封闭折线边界且无交叉边的平面图形。
多边形分类
- 凸多边形:多边形的所有内角均小于180°,它的内部完全在它的任意一边及其延长线的一侧
- 凹多边形:至少有一个内角大于180°,凹多边形某些边的延长线会与其他边相交且有时一对内点之间的连线会与多边形边界相交
- 退化多边形:常用来描述共线或重叠坐标位置的顶点集。共线顶点生成一线段。重叠顶点位置可以生成有多余线段、重叠边或长度为0的边的多边形
识别凹多边形
可以使用相邻边的叉积来测试凹凸性,凸多边形的所有向量叉积均同号,如果某些叉积取正值而另一些取负值可确定其为凹多边形。
分割凹多边形
通过坐标变换到xy平面上,如果有一个叉积的z向量为负,那么多边形为凹多边形且可沿叉积中第一边向量的直线进行切割。
旋转法分隔凹多边形:沿多边形的边的逆时针方向,逐一将顶点Vk 移到坐标系原点。然后顺时针旋转多边形,使下一顶点V k+1 落到x轴上。如果在下一个顶点V k+2 位于x轴下面,则多边形为凹,再利用x轴将多边形进行分割,并对新多边形进行重复测试。
将凸多边形分割成三角形集
一旦有了凸多边形的顶点集,通过将任意顺序的三个连续的顶点定义为一个新三角形来实现。然后将三角形的中间顶点从多边形原顶点队列中删除。
内-外测试
奇偶规则和非零环绕规则是识别平面图形内部区域的两种常用方法。
奇偶规则,从任意位置P到对象坐标范围以外的远点画一条概念上的直线(射线),确保该直线不与任何多边形顶点相交,并统计沿该射线与各边的交点数目。若与这条射线相交的多边形边数为奇数,则P为内部点,否则P为外部点。我们可以使用该过程对两个同心圆或两个同心多边形的内部填上指定颜色。
非零环绕,该方法统计多边形边以逆时针方向环绕某一特定点的次数。这个数称为环绕数。在对多边形应用非零环绕数规则时,将环绕数初始化为零。设想从任意位置P到对象坐标范围外的远处一点画一条射线。所选择的射线不能与多边形的任何顶点相交。当从P点沿射线方向移动时,统计穿过该射线的边的方向。每当多边形从右到左穿过射线时,边数加1;从左到右时,边数减1。在所有穿过的边都已计数后,环绕数的最终值决定了P的相对位置。假如环绕数为非零,则P将定义为内部点,否则P时是外部点。
一种确定有向边界穿越的方法时沿对象边建立向量(或边界线),将从P点出发的射线向量u与穿过射线的每条边的边向量E进行叉积运算。对于某一特定的边,叉积 u x E的z分量为正,那么边从右到左穿过射线,环绕数加1。否则,边从左到右穿越射线,环绕数减1。
另一种方法是使用点积代替叉积。建立与向量 u 正交且当站在 P点沿 u方向看时 从右到左方向的一个向量。如果该正交向量与边界线向量的点积为正,表示从右向左穿越,让环绕数加1。否则,边从左到右穿越射线,环绕数减1。
多边形表
场景中的对象一般用一组多边形面片来描述。
对每一个对象的描述的多边形数据分成两组:几何数据表和属性数据表。
几何数据表包含顶点坐标和标识多边形面片空间方向的参数。对象的属性信息包含指定对象的透明程度及其表面的反射性能和纹理特征。
场景中对象的几何数据简单地组织为三张表:顶点表、边表和面片表(简称为面表)。对象地每一顶点地坐标存储在顶点表中。边表包含指向顶点表地指针以确定每一多边形地边地端点。而面片表包含指向边表地指针以确定每个多边形地边。
当使用三个数据表(顶点、边和面片)时错误地检查可由图形软件包来完成地测试有:
(1)每一顶点至少有两条边以其作为端点
(2)每条边至少是一个多边形地组成部分
(3)每一个多边形都是封闭的
(4)每一个多边形至少有一条共享边
(5)如果边表包含指向多边形的指针,那么多边形指针引用的每条边都有一个反向指针指回该多边形
平面方程
平面一般方程为
假设多边形上三个连续顶点:
(x1,y1,z1),(x2,y2,z2),(x3,y3,z3)
平面系数表达式:
定义一个多边形面片的坐标有可能不在一个平面上,那么可以通过将面片分割成若干个三角形来解决。也可以为该顶点集找到一个逼*面来解决。另一种方法时将顶点集投影到一个坐标平面上。
前向面与后向面
向着对象内部的一侧称为后向面,可见或朝外的一侧称为前向面。
向量(A,B,C)为平面Ax+By+Cz+D=0的法向量。
法向量也可通过向量叉积获得,平面上任意三个顶点V1,V2,V3,那么法向量:
法向量N和平面上任意一点P可给出向量形式的平面方程:
凸多边形可以选择两个连续的边向量的叉积来获得平面参数,凹多边形可以选择用于叉积计算的两条边的夹角小于180°得出的结果作为法向量,否则取叉积反向量
OpenGL多边形填充区函数
矩形填充区域:
该矩形的两个角坐标为(x1,y1),(x2,y2),后缀码指出坐标数据类型以及是否用数组元素来表示坐标,i,s,f,d,v
使用图元变量GL_POLYGON可以显示单个多边形,例如下面有六个顶点p1到p6描述一个逆时针次序的二维多边形。
使用图元变量编程GL_TRIANGLES,就可以获得两个分开的三角形填充区。
使用图元变量GL_TRIANGLE_STRIP;可获得一组连接的三角形。在N个顶点的集合中没有重复的坐标位置,那么可获得N-2个三角形的带。
使用图元变量GL_TRIANGLE_FAN可以生成另一种相连的三角形。
使用GL_QUADS描述四边形
使用GL_QUADS_STRIP可以得到一组相连的四边形
OpenGL顶点数组
定义顶点坐标的方法:
直接用一个双下标数组:
也可以定义一个三维顶点位置的数据类型,然后给出作为单下标数组元素的每一顶点位置的坐标:
使用顶点数组可以减少处理坐标信息的函数调用数量。步骤如下:
- 引用函数glEnableClientState(GL_VERTEX_ARRAY)激活OpenGL的顶点数组特性
- 引用函数glVertexPointer指定顶点坐标的位置和数据格式
- 使用子程序如glDrawElements显示场景,该子程序可处理多个图元而仅需少量的函数调用
像素阵列图元
一个彩色像素阵列称为一个像素图。
像素阵列的参数包括指向颜色矩阵的指针、矩阵的大小及其将要影响的屏幕区域。
实现像素阵列的另一种方法是为矩阵中的每一元素赋值为0或1。此时,阵列简化为位图,有时也成为掩模,它指出一个像素是否被赋予预定颜色。
OpenGL像素阵列函数
OpenGL中有两个函数可用于定义矩形阵列的形状或图案。一个函数定义位图,另一个定义像素图。
OpenGL位图函数
width和height:阵列bitShape的列数和行数
x0和y0:矩形阵列原点的位置,该位置称为当前光栅位置
xOffset,yOffset:位图显示后更新帧缓存当前光栅位置的坐标位移
glRasterPos* () 设定当前光栅位置
使用如下程序段可将位图应用于帧缓存中:
OpenGL像素图函数
将用彩色阵列定义的图案应用到一块帧缓存的像素位置。
width,height:像素位图的列数和行数
dataFormat:何为阵列指定值,例如GL_BLUE指定所有像素都使用蓝色
dataType:指定阵列中颜色的数据类型
glResterPos:设定当前光栅位置
OpenGL有4个颜色缓存用于屏幕刷新。立体显示中左、右两个场景使用两个颜色缓存。对于立体显示缓存中的每一个,各有一对前-后双缓存用于动画显示。
使用如下命令可选择单一颜色或辅助缓存,或选择混合缓存来存储像素图:
buffer可赋以多种OpenGL符号常量,来指定一个或多个“绘图”缓存。
OpenGL光栅操作
光栅操作用于描述以某种方式处理一个像素阵列的任何功能。将一个像素阵列的值从一个位置移到另一位置的光栅操作也称为像素值的块移动或bitbit操作,尤其该功能由硬件实现时。
xmin,ymin是要提取的矩形块的左下角。
width,height,dataFormat,dateType与glDrawPixels子程序中相同。
存入参数array中的数据类型依赖于选择的缓存。
用函数glReadBuffer(buffer)
可以为glReadPixels子程序选择颜色或辅助缓存的特殊组合。
xmin,ymin是块的左下角屏幕坐标位置。
pixelValues指定要复制的数据种类:颜色值、深度值或模板值。
在OpenGL中,可以使用下面的函数来选择按位与逻辑操作,将取来的和目标的像素颜色值进行组合:
glPixelTransfer和glPixelMap可用来移动或调整颜色值、深度值或模板值
字符图元
一组字符的完整设计风格称为字样。
字体指的是一组按照特定尺寸和格式的模板字符样式。
字体可分为两大类:有衬线和无衬线。
字体也按是否有单一宽度和比例宽度而进行分类。
存储计算机字体有两种不同的表示方法。一种表示某种字体字符形状的简单办法是使用矩形网格图案。这样的字体称为位图字体。位图化的字符集有时也称为光栅字体。另一种更灵活的方法是用直线和曲线段来描述字符形状,这种字符组称为轮廓字体或笔画字体。
OpenGL字符函数
使用下面的函数可显示GLUT位图字符:
glutBitmapCharacter( font , character );
font:指定一特定字体集
character:赋以ASCII编码或其他要显示的字符
可以使用下列程序显示一个包括36个位图的文字串:
用下面的函数可以显示一个轮廓字符:
可为参数font赋值GLUT_STROKE_ROMAN来显示比例空间的字体,或赋值GLUT_STROKE_MONO_ROMAN来显示常量间隔的字体。
OpenGL显示表
在OpenGL中使用显示表的结构可以把对象描述成一个命名的语句序列(或任何其他的命令集)并存储起来既方便又高效。
创建和命名OpenGL显示表
glNewList(listID , listMode);
...
glEndList();
listID作为表名来形成一个显示表
listMode可赋以OpenGL符号常量GL_COMPILE或GL_COMPILE_ADN_EXECUTE之一。如果希望为以后执行而存储该表,则使用GL_COMPILE。否则,放入表中的命令立即执行,但仍然可以在以后再执行它。
为了避免重用标识listID而导致显示表的丢失,可以让OpenGL为我们生成一个标识,
尽管使用glGenList可生成未使用的标识,我们还是可以单独向系统查询指定整数值是否已用做显示表的名字。
执行OpenGL显示表
要执行的显示表数量赋给参数nList,而参数listIDArray是显示表标识的数组。arrayDataType用来指出数据类型。显示表标识通过listIDArray中一个元素的值与offsetValue的整数值相加得到。
删除OpenGL显示表
参数startID给出最前面的显示表标识,而参数nLists给出要删除的显示表总数。
OpenGL显示窗口重定形函数
为了允许对显示窗口尺寸的改变做出反应,GLUT提供下面的函数:
glLoadIdentity使前面任意的投影参数值对新的投影设置不起作用。
小结
一个填充区是一个显示成单色或彩色图案的平面区域。
奇偶规则和非零环绕数可用来判定平面区域的内点。
每一个多边形都有确定多边形平面空间方向的前向面和后向面。该空间方向可用与多边形平面正交且从后向面指向前向面的法向量来确定。
图形软件包中其他一些可用的图元有图案阵列和字符串。
使用OpenGL基本库中的图元函数可以生成点、直线段、凸多边形填充区和位图或像素图的图案阵列。
OpenGL生成输出图元的基本函数: