计算机图形学笔记_第1页
计算机图形学笔记_第2页
计算机图形学笔记_第3页
计算机图形学笔记_第4页
计算机图形学笔记_第5页
已阅读5页,还剩53页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、计算机图形学笔记一 图形系统基础概念坐标系统: 在图形学中通常包括以下几种笛卡尔坐标系: a 建模坐标系(局部坐标系) b 世界坐标系 c 观察坐标系 (摄像机坐标系) d 设备坐标系(屏幕坐标系). 在构建一个场景的过程如下,先场景中每个对象的各自的建模坐标系(局部坐标系)中构建冲该对象的几何形状, 比如桌子和树木,在3d虚拟世界每个物体都有自己的坐标系-自己的原点和坐标轴。对象与子对象之间和可能存在嵌套坐标系(父子关系),比如左眼睛在(-100,400,0), 右眼(100,400,0) 鼻子(0,300, 0) 嘴巴 (0, 100, 0) 他们的位置是对于父对象脸的建模坐标系来,而他们

2、自己也拥有各自的坐标系。 一旦指定完成每个对象的形状,我们就将其放入成为世界坐标系的场景参照坐标系的适当位置上。 在建模坐标系和世界坐标系可以用任何浮点数和整数数值来描述,而不用受到设备的约束; 在搞好场景所有部分后,需要确定场景中那些物体需要显示出来,这就需要建立观察坐标系来确定观察者(摄像机)的位置和观察范围,和场景中的物体在观察坐标系中的位置。 确立以后,在通过二维投影映射到设备坐标系上,完成由虚拟场景到显示器2维屏幕的显示。图形输出原语(graphics output primitive) :图形的基本构造块,是最基本的图形元素;包括字符串和几何成分,如点/直线/曲线/填充区域(通常为

3、多边形)以及由色彩阵列定义的形状。简称图元, 描述几何要素的图元一般称为几何图元.二 输出光栅图元的相关的算法画线算法:线段是由在坐标系中的两头端点(顶点)来确定的,要在光栅显示器上显示线段,图形系统必须把两端点的整数投影到整数屏幕坐标,并确定两端点间直线路径最近的像素的位置,接下来将颜色值装入帧缓冲区内的对应像素的地址.。 视频控制器从帧缓冲区读出写入的颜色值并绘制在对应屏幕坐标的像素单元上。这一过程是将一线段的数字化为离散的整数位置。但光栅线段特有的阶梯现象在低分辨率系统中特别容易看出来,成锯齿形,如下图。yxO直线方程: y=kx + b 截距式方程 斜率:k=(y1-y0)/(x1-x

4、0) 截距: b=y0 kx0在光栅系统中,通过像素绘制直线,水平和垂直方向的步长都受到像素间距的现在。也就是说必须在离散的位置上对直线进行采样,并且在每个采样位置上确定距离直线最近的像素,如下图。对于任意沿着直线方向给定的x的增量x,可以从下面公式计算对于y的增量y y = k * x 同样 x = y/ kY1Y0X0X1DDA算法(Digital Differential Analyzer) 在坐标轴上一单位间隔对线段进行取样,从而确定坐标轴上里线段路径最近的整数值。 首先考虑斜率k, 如果k小于1, 则在x轴按x=1进行取样,逐个计算对应的每一个y值 yi+1 = yi+m, i为整数

5、, 计算出来的y值通过四舍五入取得整数y;而对于k1时,则交换x和y的位置, xi+1 = xi + 1/k 此时每个计算出的x值要按y扫描线四舍五入到最近的像素位置。 上述是按左端点到右端点的假设,如果从右向左则相反,由加变减号。DDA算法的优点是快, 利用光栅特效消除了直线方程中的乘法,但取整的误差的累积使得较长线段所计算的像素偏离实际线段,而取整和迭代浮点运算仍然十分耗时。Bresenham 画线算法一种精确有效光栅线生成算法,是为了“显示器(屏幕或打印机)系由像素构成”的这个特性而设计出来的算法,使得在求直线各点的过程中全部以整数来运算,因而大幅度提升计算速度。 另外Bresenham

6、还可以用于显示圆形和其它曲线。原理是以过各行、各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺序计算直线各垂直网格线的交点,然后确定该列像素中与此交点最近的像素。 该算法的优点在于可以采用增量计算,使得对于每一列,只要检查一个误差项的符号,就可以确定该列所求的像素详细推导过程: 以斜率小于1为例子,沿着线路径的像素位置以单位x为间隔(为1个像素距离)来确定。 从最左端点(x0, y0) 开始,逐步处理后继列(x的位置),并在屏幕上y值最接近线段的那一个像素上绘制出一点。如果要显示的像素在(xi,yi), 那么下一步需要确定在列xi+1 =xi + 1上绘制像素,始终(xi+1,yi),还

7、是(xi+1, yi+1),在位置xi+1,我们使用dlower和dupper来标识两个像素与数学上线路径的垂直偏移,在像素xi+1处直线y实际坐标可计算为:y=k * (xi+1) + b dlower = y yi = k (xi + 1) + b yi;dupper = (yi + 1) y = yi + 1 - k (xi + 1) bdlowerdupperyxoyiyi+1xi + 1要确定两个像素哪个更接近线路径,需要测试这两个像素偏移的差值。dlower dupper = 2k(xi + 1) 2yi +2b 1通过第i步的决策参数的pi, 从而只是用整数进行计算,设y和x分别

8、是两线段两端点的垂直和水平增量,斜率k=y/x, 那么决策参数Pi: pi = x * (dlower dupper)将dupper dlower k 代入得,pi= 2y*xi 2x*yi+c, pi的符号与dlower dupper相同(因为例子中x0), 参数c也是常量,c=2y + x(2b-1),而且会在循环计算Pi时被消除, 加入Yi处像素Yi+1处更接近线段(dlower dupper),那么Pi是负的,此时绘制上面的像素,反之绘制下面的。直线上坐标会沿着x或y的单位长度(1个像素)的距离变化,因此可以利用递增整数运算得到后继的决策参数: pi+1= 2y*xi+1 2x*yi+

9、1+cPi+1 pi = 2y (xi+1 - xi) 2x (yi+1 -yi) 又因为xi+1 = xi + 1 所以pi+1 = pi + 2y 2x(yi+1 - yi) ,其中yi+1 yi 为0或为1 ,取决于pi的符号。 决策参数的递归运算从线段的坐标端点开始每个整数x位置进行,起始像素位置(x0,y0)的第一个参数p0通过等式pi= 2y*xi 2x*yi+c获得 p0 = 2y x当|k1|时的Bresenham画线算法1. 输入线段的两个端点,并将左端点存储在(x0,y0)中;2. 将(x0,y0)装入帧缓存,画出第一个点;3. 计算常量x,y 和 2y x,得到决策参数的

10、第一个值p0 = 2y x;4. 从i=0,开始,在沿着路径的每个xi处,进行下列检测:如果pi 0, 下一个要绘制的点是(xi + 1, yi) 并且pi+1 = pi + 2y 否则下一个要绘制的点数(xi + 1, yi + 1),并且pi+1 = pi +2y -2x5. 重复步骤4,共x-1次.并行画线算法如有多个处理器,可将线段计算分割给每个处理器来运算。 给定n个处理器,那么可以把线段分割为n个子线段,并在每个子线段进行Bresenham画线算法。对于0k1且左端点位置为(x0,y0)的线段,我们沿着x访问对线段进行分割。相邻线段的起始x位置间距离可以寄计算为xp = (x +

11、n 1)/n (考虑到x=1这种为单位长度的分配任务情况),从1开始编号的话,那么第i分段的起始x坐标等于 xi = x0 + xp * (i-1)。为了将Bresenham算法用于各个分段,必须得到各个分段x与y的增量yp xp ; yp = k * xp 第i分段起始y坐标yi = y0 + round( (n - 1) *yp );那么第i分段的决策参数pi 可以推出 (n-1)xp * (2y) round( (n - 1) *yp )(2x) + 2y-x圆生成算法圆的特性圆可以定义为所有距离中心点(xc,yc)同等距离R的点的集合,这个距离关系可以用勾股定理得到(y-yc)2 +

12、(x-xc)2 = r2 但这并非生成圆最好的方法,因为这个方法每一步都包含大量的运算. 另一种方法是使用极坐标,来计算圆周的点,以参数极坐标形式表示圆的方程X = xc + r* cosy = yc + r * sin 但上述方法三角函数的计算十分耗时, 利用圆的对称性可以减少计算量。 可以将圆化为4份或8分,利用方程确定圆周上的像素位置,仍然需要大量计算时间。更有效的方法是如同Bresenham画线算法一样通过决策参数的增量计算为基础,这样的话仅仅需要整数运算。中点画圆算法如同光栅画线算法,我们在每个以单位间隔(1像素)取样,并确定离指定圆最近的像素位置。 对于给定半径r和中心(xc,yc

13、),从而把计算出的每个位置(x,y)移动到合适的屏幕位置。 可以在八分圆的正x方向取单位步长,并用决策参数来确定每一步两个可能y的位置,哪个更接近于圆的位置。然后通过对称性来得到剩下7分圆。定义圆的函数fcirc(x,y) = x2 + y2 r2, 半径为r的任意一点(x,y) 满足方程fcirc(x,y) = 0; 如果点在圆内,圆函数为小于0; 如果点在圆外,圆函数大于0;在给出取样位置xk+1上两个候选像素间的中点,假设刚在(xk,yk)上绘制了一个像素,下一步需要确定的是像素位置(xk+1,yk)还是(xk+1,yk-1)更接近于圆。我们的决策参数是通过圆函数方程在这两个像素的中点求

14、值而得到的:pk = fcirc(xk+1,yk-1/2),如果pk0,那么这个点位于圆内,yk 更接近于圆边界。否则,中点位于圆外或圆边界上,我们选择yk-1.后续的决策参数可以使用增量运算得到.Pk+1 = fcirc (xk+1 +1, yk+1 -1/2) = (xk+1)+12 + (yk+1 1/2)2 r2 = pk + 2(xk + 1) + ( yk+12 yk2) (yk+1 yk) + 1 其中yk+1 是yk 或 yk -1, 取决于pk的符号pkykYk-1XkXk+1如果pk0 说明,中点在圆内,yk+1=yk,否则在圆外,yk+1=yk - 1增量dp = Pk+

15、1 pk = 2(xk + 1) + (yk+12 yk2) (yk+1 yk) + 1Pk+1 = pk + dp又因为yk+1 等于yk 或者 yk-1 取决于pk的符号, 代入求得增量 dp=2xk + 3=2xk+1 + 1 (yk+1 = yk时)或 dp = 2xk+1 + 1 2yk+1 (yk+1 = yk- 1 时)在起始位置(0, r)处,这两项的值是0和2r, 2xk+1 每个后续值都可以通过前一个值加2得到, 2yk+1同理.P0 = fcirc (1, r-1/2) = 1+ (r -1/2)2 r2 或 p0 = 5/4 r假如将半径指定为整数,就可以对p0进行简单

16、的取整:P0 = 1-r,因为所有增量都是整数中点画圆法的步骤1 输入圆的半径r和圆心(x,y), 并得到圆周(圆心在原点)上的一个点;2计算决策参数的初始值 p0 = 5/4 r;3在每个xk位置, 从k=0开始,完成下列测试:假如Pk = yo椭圆生成算法椭圆的特征 如果一个平面切截一个圆锥面, ,且不与它的底面相交,也不与它的底面平行,则圆锥和平面交截线是个椭圆.穿过两焦点并终止于椭圆上的线段AB 叫做长轴。长轴是通过连接椭圆上的两个点所能获得的最长线段。穿过中心(两焦点的连线的中点)垂直于长轴并且终止于椭圆的线段 CD 叫做短轴。半长轴(图中指示为a)是长轴的一半:从中心通过一个焦点到

17、椭圆的边缘的线段。类似的,半短轴(图中指示为b)是短轴的一半。离心率椭圆的形状可以用叫做椭圆的离心率的一个数来表达,习惯上指示为。离心率是小于 1 大于等于 0 的正数。离心率 0 表示着两个焦点重合而这个椭圆是圆。对于有半长轴a和半短轴b的椭圆,离心率是.离心率越大,a与b的比率就越大,因此椭圆被更加拉长。半焦距c等于从中心到任一焦点的距离,则.距离c叫做椭圆的线性离心率。在两个焦点间的距离是 2a。椭圆上任意一点到椭圆的两个焦点的距离之和都等于一个常数, 椭圆上任意一点P(x,y)到两个焦点的距离d1,d2, 那么d1+d2 = 常数.可得椭圆方程x-x12+y-y12+x-x22+y-y

18、22=常数对方程求平方,去除剩余的根,再平方,可得椭圆一般式方程 Ax2+By2+Cxy+Dx+Ey+F=0, 其中系数A,B,C,D,E,F可以依据焦点坐标和长轴和短轴的尺寸求得在任意方向指定一个椭圆的交互方式是输入椭圆的两个焦点和椭圆边界上的一点,利用这三个坐标,可以求出常数,然后可以再求出一般式中的系数,并利用方程生成沿途像素如果短轴和长轴按坐标轴x,y轴方向分别平行,那么椭圆方程可以大大简化。可改写为x-xc2rx+y-yc2ry=1oxyycxcryrx利用极坐标r和,也可以按照参数方程的形式来描述标准位置的椭圆X=xc+ rxcosy=yc+ rysinr称为包围半径,是包围这个椭

19、圆的圆的半径,称为椭圆离心角和圆的算法一样,利用其对称性可以减少计算量。 标准位置椭圆在四分象限是对称,和圆不一样,圆可以在八分象限对称。中点椭圆算法中心点画圆法将第一象限分为两部分, 斜率绝对值小于1和大于1, 在斜率绝对值小于1的区域内x方向取单位步长,斜率绝对值大于1的区域内以y方向取单位步长。区域1和区域2可以通过多种方法进行处理。可以从位置(0,ry)开始,在第一象限内沿椭圆路径顺时针步进;当斜率小于-1将x方向的单位步长专为y方向的单位步长。反过来,也可以从(rx,0)开始,以逆时针方式取得点和上面刚好相反。利用并行处理器可以同时计算两个区域类的像素位置。作为中心椭圆算法的串行实现

20、,则以(0,ry)为起点,在第一象限顺时针沿椭圆路径前进xyryrx区域1区域2斜率=-1去(xc,yc)=(0,0) 定义椭圆函数为felipsex,y=ry2x2+rx2y2-rx2ry2 felipsex,y0 (x,y)在椭圆边界外 ; felipsex,y = 0 (x,y)在椭圆边界上 ,因此用椭圆felipsex,y的中点做决策参数,在每个位置取样,根据椭圆函数沿椭圆轨迹对两个候选像素间中点求值来确定一下个像素.从(0, ry)开始,在x方向取单位步长直到区域1和区域2之间的分界处,然后转为y方向的单位步长再覆盖第一象限的剩余曲线段. 每一步都需检查曲线斜率值。K=dy/dx =

21、 -2ry2x2rx2y ,在区域1和区域2的交界处,在区域1和区域2的交界处,dy/dx = -1 且 2ry2x=2rx2y ;因此移除区域1的条件是2ry2x 2rx2y那么区域1的决策参数p1k=felipsexk+1,yk-12= ry2(xk+1)2+rx2(yk-12)2-rx2ry2 如果p1k0 那么中点在椭圆内,yk上的像素更接近于椭圆边界。 否则,中点在椭圆外或椭圆边傻瓜,yk上像素应该在yk-1上下一个取样位置(xk+1+1=xk+2), p1k+1=felipsexk+1+1,yk+1-12=ry2(xk+1)+1)2+rx2(yk+1-12)2-rx2ry2 其中y

22、k+1根据p1k的符号取值为yk或yk-1通过上面可以算出决策参数的增量dp = p1k+1-p1k = 2ry2xk+1+ry2 或者 = 2ry2xk+1+ry2 -2rx2yk+1p10=felipse 1,ry-12=ry2+rx2(ry-12)2-rx2ry2或=ry2-rx2ry+1/4rx2 ykYk-1XkXk+1Xk+2中点pk中点pk+1区域2变成以y为单位步进,p2k=felipse(xk+12,yk-1), 推导过程同理中心椭圆算法步骤1 输入rx,ry和椭圆中心(xc,yc), 并得到椭圆(中心在原点上)的第一个点(x0,y0) = (0, ry)2 计算区域1中决策

23、参数的初始值p10=ry2-rx2ry+14rx23 计算区域1中每个xk的位置,从k =0开始, 完成下列测试; 如果p1k0 ,沿中心,在(0,0)的椭圆的下一个点为(xk,yk-1),并且p2k+1=p2k-2rx2yk+1+rx2 假如p2k0,沿中心,在(0,0)的椭圆的下一个点为(xk+1,yk-1) 并且p2k+1=p2k-2rx2yk+1+2ry2xk+1+rx2 使用与区域1中相同的x,y增量进行计算,直到y= 06 确定其他三个象限的对称点7 划拨给计算出的每个像素位置(x,y)移到中心在(xc,yc)的椭圆轨迹上,按坐标轴绘制点x = x +xc, y=y+yc其他曲线方

24、法类似圆和椭圆的绘制算法多边形填充区数学上定义为三个或更多顶点坐标位置描述的平面图形;是平面的封闭、由有限线段(大于2)组成,且首尾连接起来划出的形状。多边形的分类凸多边形:多边形的内角均小于180度,那么该多边形为凸多边形,凸多边形的一个等价定义是它的内部完全在它任意一便及其延长线的一侧。凹多边形: 一个非凸的多边形被称作凹多边形2或凹角.3凹多边形至少有一个内角大于180度.退化多边形:共线或重叠坐标位置的顶点集;可能有多余线段,重叠边,或者长度为0的边。识别凹多边形凹多边形至少有一个内角大于180度,如果为每一条边建立一个向量,则可以使用相邻边的叉积来测试凹凸性。凸多边形的所有向量叉积均

25、同号。如果某些叉积取正值,某些为负,那么可以断定为凹多边形。V1V2V3V3V4V5E1E2E3E4E5E6XY(E1 x E2) 0(E2 x E3) 0(E3 x E4) 0(E4 x E5) 0(E5 x E6) 0(E6 x E1) 0凹多边形分割凸多边形向量法通过顺序计算各个连续边向量的叉积,如果有些叉积的z分量为正,一些为负。 那么可延叉积中第一边向量执行进行切割。EK = VK+1 - VKE1E2E3E4E5E6V1V2V3V4V5V6旋转法1、对多边形的一个顶点Vi,平移多边形使Vi位于坐标原点;2、绕原点旋转多边形,使Vi+1落在X轴的正半轴上;3、检查第i+2个顶点y坐标

26、分量的符号。如果符号为正或零,那么多边形在该边处是凸的;反之,则是凹的。分割多边形。4、分割多边形的时候,检查第i+2个顶点后面的各顶点的y坐标分量,直至发现一个顶点的y坐标分量大于或等于零。这个顶点在x轴的上方,或恰好落在x轴上,记为Vi+j。那么,分割下来的多边形为Vi+1Vi+2.Vi+jVi,剩下的多边形为ViVi+1Vi+j.Vi。5、多分割的多边形再次使用该算法,直到它们都为凸多边形。这个算法也可以以一边为参考,判断其他顶点在这一边的方向(左、右)来确定多边形的凹凸性;分割多边形时步骤1、以多边形的一边AB为参考,判断其他点在AB的那一边,直到一点反向(比如这一点为点C),然后连接

27、BC对多边形进行分割;2、再根据此算法对分割出来的多边形继续进行分割。内 外测试不自交的多边形:多边形仅在顶点处连接,而在平面内没有其他公共点,此时可以直接划分内-外部分。自相交的多边形:多边形在平面内除顶点外还有其他公共点,此时划分内-外部分需要采用以下的方法。 (1)奇-偶规则(Odd-even Rule):奇数表示在多边形内,偶数表示在多边形外从任意位置p作一条射线,若与该射线相交的多边形边的数目为奇数,则p是多边形内部点,否则是外部点。 (2)非零环绕数规则(Nonzero Winding Number Rule):若环绕数为0表示在多边形内,非零表示在多边形外首先使多边形的边变为矢量

28、。将环绕数初始化为零。再从任意位置p作一条射线。当从p点沿射线方向移动时,对在每个方向上穿过射线的边计数,每当多边形的边从右到左穿过射线时,环绕数加1,从左到右时,环绕数减1。处理完多边形的所有相关边之后,若环绕数为非零,则p为内部点,否则,p是外部点。判断点p是否在多边形内,从点p向外做一条射线(可以任意方向),多边形的边从左到右经过射线时环数减1,多边形的边从右往左经过射线时环数加1,最后环数不为0,即表示在多边形内部。当然,非零绕数规则和奇偶规则会判断出现矛盾的情况,如下图所示,左侧表示用奇偶规则判断绕环数为2 ,表示在多边形外,所以没有填充。右侧图用非零绕环规则判断出绕数为2,非0表示

29、在多边形内部,所以填充。另外一个例子,如下平面方程这个方程是法向量(垂直与这个平面)和一个在这个平面已知的点在3D空间中定义的。假设平面的法向量,还有在这个平面上已知的点P1 和在这个平面上的任意一点PGraph of a plane in 3D我们可以在平面上定义一个向量连接P1到P, ,由于向量和法向量相互垂直,所以点积的结果因该为0这个向量与法向量的点积在平面上成为这个的平面的方程,通过计算点积,我们得到如果我们替换常数项,那么平面方程可以简化平面与原点的距离如果法向量归一化,那么平面方程的常数项d将成为与原点的距离Plane with unit normal如果单位法向量(a1,b1,

30、c1)和点P1(Da1,Db1,Dc1)在平面上,D将成为与原点的距离。为了展示距离D是方程的常数项,这个平面方程可以用单位向量和点来改写。 因此,我们用(归一化的)法向量的长度来确定原点与标准平面方程的距离,例如原点与下面用法向量(1,2,2)的平面方程的距离是2平面与点的距离从点P2到平面最短距离可以被计算为两个向量和的点积,然后投影向量到这个平面的法向量,通过下图可以看出Distance between Plane and Point那个平面方程和一个点P2的距离D:将上面方程的分子部分扩展开最终,将它代入前面的方程求得距离公式看起来像是插入点P2到平面方程除以法向量的长度,例如点(-1

31、, -2, -3)到平面x + 2y + 2z - 6 = 0的距离等于注意的是这个距离是有符号的,可以为负值,它用以点的方向,例如:如果距离是正值,这个点与法向量的指向在同一面,如果为负值,意味着这个点在另外一面基本图形管线如上图OpenGL的图形管线客户端与服务器设计模式:客户端的与服务器的那边分离,在OpenGL中客户端的代码存在于执行的应用程序中主CPU的内存中,或者在是主系统内存中的驱动程序,驱动将组合/渲染命令和数据发送到服务器端去执行;而服务器实际上是图形卡上的硬件和内存。 客户端和服务器两者异步独立执行,这样才能达到最大的效能。客户端装配块数据和命令到缓存中,然后发送给服务器;

32、服务器处理缓存中的这些内容。如果客户端同一时刻准备将下一次渲染的数据位和信息发送,或者服务器处理完等待客户端,或者客户端等待服务返回数据和命令;这种情况叫管线停滞,管线停滞会影响程序的性能Shader图形处理的基础执行单元, 着色器程序Vertex shader: 处理来自客户端的信息,并对它们进行几何转换/光照计算/置换/色彩值。Fragment shader 对于已经装备好的图元的片段,FragmentShader将图元分解为一系列像素单元的大小的片段,并对其进行颜色填充。 Shader传输的三种基本数据Attributes 属性:每个顶点都可改变的数据元素,例如顶点的位置,opengl中

33、它存储在一个有四个分量的向量中,x,y,z 三个坐标信息,还有一个分量W. 其它的属性还有纹理坐标,色彩值,表面法线。 属性是客户端存储在本地内存中的缓存指针在图形设备上的拷贝。 属性只应用在Vertex Shader上。Openg可以支持16个通用属性,从0到15编号属性名 描述GLT_ATTRIBUTE_VERTEX 顶点位置的三分量(x,y,z)GLT_ATTRIBUTE_COLOR 颜色分量(r,g,b,a)GLT_ATTRIBUTE_NORMAL 表面法线的三个分量(x,y,z)GLT_ATTRIBUTE_TEXTURE0 纹理坐标的主分量 (s, t) GLT_ATTRIBUTE_

34、TEXTURE1 纹理坐标的第二分量(s, t)Uniforms 一组的值, Uniforms最普遍的应用是在VertexShader中设置矩阵的变换,可以是标量或向量类型。Texture纹理 : 纹理信息Outs : shader之间输入输出的变量几何转换Transformation简单中的几种变换视图View : 其实上就是变换观察者或者摄像机的位置模型Modeling : 在场景中移动,旋转, 缩放物体模型视图ModelView: 描述视图和模型的对偶像, 视图和模型变换其实是一致的,模型视图将其进行合并投影:Projection 改变可视区域的大小和形状,将3D空间转换为2d平面视口V

35、iewport : 实际上是一种伪变换,对窗口的输出进行缩放几何转换过程:将原始的顶点数据1X4的矩阵x,y,z和缩放因子w, 然后将其与模型视图矩阵相乘,经过视图模型变换后的视觉坐标(对于观察者和摄像机而言)。然后将这个视觉坐标与投影矩阵相乘,产生剪裁坐标,这样就消除了所有可视区域之外的所有数据,这个剪裁坐标可随后除以w,产生规范化的设备坐标。W值可能会被投影矩阵和视图矩阵所修改,具体取决与顶点发生的变换。几何数据顶点位置,和标准向量(normal vectors),在OpenGL 管道raterization 处理过程之前可通过顶点操作(Vertex Operation)和基本组合操作改变

36、这些数据。模型坐标Object Coordinates对象的本地坐标系任何变换之前的最初位置.为了变换(transformation)这些对象,可以调用glRotate(),glTranslatef(),glScalef()这些方法。视觉坐标Eye Coordinates使用GL_MODELVIEW矩阵和Object 坐标相乘所得。在OpenGL中用GL_MODELVIEW将对象对象空间(Object Space)变换到视觉空间(eye space)。GL_MODELVIEW矩阵是模型矩阵(Model Matrix)和视觉矩阵(View Matrix)的组合()。其中,Model 变换指的是将

37、对象空间转换到世界空间(世界空间指的是OpenGL中的三维空间),而View 变换是将世界空间变换到视觉空间注意:在OpenGL中没有单独的摄像机/视图矩阵。因此,为了模拟摄像机或者视图的变换,其中的场景(3D物体和光照)必须通过和视图相反的方向变换。也就是说,OpenGL总是将摄像机定义在(0,0,0)点,并且强制在视觉空间的-Z轴方向,而且不能变换。法向量(Normal vectors)从对象坐标系(Object coordinates)变换到视觉坐标系(eye coordinates),它是用来计算光照(lighting calculation)的.注意标准向量(Normal vecto

38、rs)的变换和顶点的不同。其中视觉矩阵(view matrix)是GL_MODELVIEW逆矩阵的转置矩阵和标准向量(Normal vector是)相乘所得,即:更多关于标准向量变换(Normal Vector Transformation)的资料可连接到此处: 剪裁坐标系(Clip Coordinates)视觉坐标系和GL_PROJECTION矩阵相乘,得到剪切面坐标系。GL_PROJECTION矩阵定义了可视的空间(截头锥体)(译注:关于什么是截头锥体,我还查了下资料,发现它是这个样子的:,这个就是投影的效果啦)以及顶点数据如何投影到屏幕上(视角或者正交化(orthogonal)),它被称

39、为剪切面坐标系的原因是(x,y,z)变换之后要和w比较。标准化设备坐标系(NDC)将剪切面坐标系除以w所得.它更像是窗口坐标系,只是还没有转换或者缩小到屏幕像素。其中它取值范围在3个轴向从-1到1标准化了。窗口坐标系(Window Coordinates)/屏幕坐标系(Screen Coordinates)将标准化设备坐标系(NDC)应用于视口转换。NDC将缩小和平移以便适应屏幕的透视。窗口坐标系最终传递给OpenGL的管道处理变成了fragment。glViewPort()函数用来定义最终图片映射的投影区域。同样,glDepthRange()用来决定窗口坐标系的z坐标。窗口坐标系由下面两个方

40、法给出的参数计算出来glViewPort(x,y,w,h);glDepthRange(n,f);视口转换公式很简单,通过NDC和窗口坐标系的线性关系得到:OpenGL 转换矩阵OpenGL使用4x4矩阵变换。注意,这16个元素存储在1D数组中,这些元素按列顺序排列。假如你想以行为顺序排列,你需要转置该矩阵。OpenGL有4种不同的矩阵:GL_MODELVIEW,GL_PROJECTION,GL_TEXTURE和GL_COLOR.你可以在代码中使用glMatrixMode()函数改变当前的类型。例如,为了选择GL_MODELVIEW矩阵,可以这样:glMatrixMode(GL_MODELVIE

41、W);-模型视图矩阵(GL_MODELVIEW)GL_MODELVIEW矩阵在一个矩阵中包含view矩阵和model 矩阵,为了变换view(camera),你需要将整个场景施以逆变换。gluLookAt()用来设置视图变换最右边的三个矩阵元素(m12,m13,m14) 是用作位移变换glTranslatef().的。m15元素是齐次坐标,该元素是用来投影变换的。3个元素集(m0,m1,m2),(m4,m5,m6)和(m8,m9,m10) 是用作欧拉变换和仿射变换,例如glRotate(),缩放glScalef().注意这三个元素集实际上指得是3个正交坐标系:(m0,m1,m2): +X 轴,

42、向左的向量(left vector)(估计是相对屏幕自己来说),默认为(1,0,0)(m4,m5,m6) : +Y轴,向上的向量(up vector),默认为(0,1,0)(m8,m9,m10): +Z轴,向前的向量,默认为(0,0,1).4 columns of GL_MODELVIEW matrix我们能够不使用OpenGL变换函数,直接构造GL_MODELVIEW矩阵。下面有一些有用的代码构建GL_MODELVIEW矩阵1. Angles to Axes 转向角度直接影响到OpenGl GL_MODELVIEW矩阵的前三列,精确的说是x,y,z的正方向轴元素。例如,如果一个单位向量沿着X

43、轴 (1,0,0)被一个任意的3X3旋转矩阵相乘,其结果是选择后的向量这意味第一列(m0, m1, m2)代表了坐标左轴的旋转矩阵,同样的,第二列对于上轴,第三列对应前轴。下面详解构建带旋转角度的GL_MODELVIEW矩阵单轴旋转Axis Rotations首先,我们看一个围绕+X,+Y,+Z每个轴的旋转; 我们设置三个轴放置在一个平面的3条不同方向,所以我们要将这个轴旋转来面朝你, 正旋转直接变成逆时针方向(右手法则)对于围绕X轴的旋转初始化Y轴和Z轴的值为(0,1,0)和(0,0,1),如果X轴旋转了A度,那么新的(Y)轴变成(0, cosA, sinA)还有新的(Z)轴变成(0, -s

44、inA, cosA).,把新产生的轴代入原来的矩阵替换掉对应的列分量,这个选择矩阵会变成这样对于围绕Y轴的旋转现在,我们旋转Y向量,将它面朝你旋转B角度,X轴从(1,0,0)变换为X (cosB, 0, -sinB).,而Z轴从(0,0,1)变换为Z (sinB, 0, cosB).对于围绕Z轴的旋转如果你旋转Z轴C度,那么原始的X轴(1, 0, 0)变成X (cosC, sinC, 0) ,而Y轴(0, 1, 0) 变成Y (-sinC, cosC, 0).组合轴旋转 Angles to Axes我们可以用三个矩阵相乘来组合三个分离的轴旋转到一个矩阵中,注意矩阵乘法的位置是不可以交换的,以至

45、于成为不同的矩阵乘法的命令而来不同的结果输出。有6种组合RxRyRz, RxRzRy, RyRxRz, RyRzRx, RzRxRy和 RzRyRx.用C+语言实现RX,RY,RZ组合旋转例子,结果包含左,上,前轴可以用于构建GL_MODELVIEW矩阵struct Vector3 float x; float y; float z; Vector3() : x(0), y(0), z(0) ; / initialze when created;/ convert Euler angles(x,y,z) to axes(left, up, forward)/ Each column of th

46、e rotation matrix represents left, up and forward axis./ The order of rotation is Roll-Yaw-Pitch (Rx*Ry*Rz)/ Rx: rotation about X-axis, pitch/ Ry: rotation about Y-axis, yaw(heading)/ Rz: rotation about Z-axis, roll/ Rx Ry Rz/ |1 0 0| | Cy 0 Sy| |Cz -Sz 0| | CyCz -CySz Sy |/ |0 Cx -Sx|*| 0 1 0|*|Sz

47、Cz 0| = | SxSyCz+CxSz -SxSySz+CxCz -SxCy|/ |0 Sx Cx| |-Sy 0 Cy| | 0 0 1| |-CxSyCz+SxSz CxSySz+SxCz CxCy|/void anglesToAxes(const Vector3 angles, Vector3& left, Vector3& up, Vector3& forward) const float DEG2RAD = 3.141593f / 180; float sx, sy, sz, cx, cy, cz, theta; / rotation angle about X-axis (pi

48、tch) theta = angles.x * DEG2RAD; sx = sinf(theta); cx = cosf(theta); / rotation angle about Y-axis (yaw) theta = angles.y * DEG2RAD; sy = sinf(theta); cy = cosf(theta); / rotation angle about Z-axis (roll) theta = angles.z * DEG2RAD; sz = sinf(theta); cz = cosf(theta); / determine left axis left.x =

49、 cy*cz; left.y = sx*sy*cz + cx*sz; left.z = -cx*sy*cz + sx*sz; / determine up axis up.x = -cy*sz; up.y = -sx*sy*sz + cx*cz; up.z = cx*sy*sz + sx*cz; / determine forward axis forward.x = sy; forward.y = -sx*cy; forward.z = cx*cy;2. Lookat to Axes 观察坐标系这个旋转矩阵可以被在3d空间的中2或3个点构成的一个观察向量所构造,如果一个对象在P1面朝P2,这

50、个观察向量就是P2- P1.首先,前轴(Z)向量计算很简单,直接由观察向量归一化得到其次,左轴(X)的向量是由特定的上方向向量和前轴(Z)的叉积来计算求得,这个上向量可以确定这个对象的滚转roll角度,还有它没有必要垂直于前(世界坐标系的Z)轴,如果你不考虑向前滚转旋转这个对象,那么我们用(0,1,0)代替它,意味着这个对象是正立的实际上上轴向量,它正交与前和左轴,由前和左的叉积计算的到,左和上轴以便后来的叉积有单位长度应该被归一化。计算左,上,前轴观察向量的C+实现代码/ minimal implementation of Vector3 structstruct Vector3 float

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论