1、Computer Graphics章三维空间的观察Computer Graphics 第六章 三维空间的观察v 主要讨论 投影的数学表示 三维观察中的投影 视见体到规范视见体的变换 用三维规范体裁剪在三维视见体内裁剪三维物体投影变换至视口二维图形图6.1 三维观察的概念模型Computer Graphics 6.1 投 影 v 什么是投影变换什么是投影变换(或投影变换的作用或投影变换的作用):):由于显示器和绘图机只能用二维空间来表示图形,要显示三维图形就要把三维坐标表示的几何形体变换成二维坐标表示的图形,这就是图形的投影变换投影变换。v 投影变换的要素投影变换的要素 视点(投影中心),投影平
2、面 投影线,投影v 投影变换的类型投影变换的类型 透视投影透视投影:投影中心和投影面之间的距离是有限的 平行投影平行投影:投影中心和投影平面之间的距离是无限的 根据投影方向与投影平面之间的关系,平行投影分为正投影正投影与斜投影斜投影视点投影平面投影线Computer Graphics 6.1.1 透视投影 图6.3 为 的投影PQCoPQCxyzPQ图6.4 在 平面上的正投影oxzPQCzxo pxxcxzcz 在坐标系 中来讨论投影,假定投影平面是 。设视点 ,空间中任一点 在 平面上的投影为 zyxo0z),(ccczyxC),(zyxQ0z)0 ,(ppyxP,如图6.3所示,则下式成
3、立:ccccpccpzzzyyyyxxxx(6.1)Computer Graphics平面上的正投影分别为 透视投影的计算公式,Q,PC,Q,PCzxo设 在则式(6.1)的几何意义如图6.4所示。zzzyyyyzzzxxxxccccpccccp)()((6.2)写成齐次坐标表达式为:11000000zyxzyzxzqyxcccccqq(6.3)qyyqxxqpqp ,(6.4)由式(6.1)得:图6.3 为 的投影PQCoPQCxyzPQ图6.4 在 平面上的正投影oxzPQCzxo pxxcxzczComputer Graphics 6.1.2 平行投影 v 平行投影分为正投影与斜投影 正
4、投影正投影:投影方向与投影平面法向相同。常见的正投影类型有:正视图投影:俯视图投影:侧视图投影:等轴测投影:投影平面的法向与每个坐标轴的夹角相等;斜投影斜投影,常见的斜投影类型有:斜等测投影:投影方向与投影平面成45度角;斜二测投影:投影方向和投影平面的夹角为arctan(2)。图6.5 三视图正 视图侧 视图原 物体俯视图(a)斜等测投影(b)斜二测投影图6.6 斜投影Computer Graphics轴测投影 axonometric projectionv轴测投影是平行投影的一种,可以使三个坐标面在一个投影上都能看到,从而具有立体感。v定义:将物体连同其参考直角坐标系,沿不平行于任一坐标面
5、的方向,用平行投影法将其投射在一个投影面上所得到的图形。Computer Graphics轴测投影v通过轴测投影绘出的图形,称为“轴测图”。轴测图在工程技术及其他科学中常有应用。v在轴侧图中,物体上与任一坐标轴平行的长度均可按一定的比率来量度。三轴向的比率都相同时称为“等测投影”,其中两轴向比率相同时称为“二测投影”,三轴向比率均不相同时称为“三测投影”。轴测投影中投射线与投影面垂直的称为“正轴测投影”,倾斜的称为“斜轴测投影”。Computer Graphics 平行投影变换公式 设投影方向为 ,空间点 在投影平面上的投影为 ,由于是沿 方向投影,所以下式成立:),(dddzyx),(zyx
6、)0,(ppyx),(dddzyxddpdpzzyyyxxx(6.5)所以zzyyyzzxxxddpddp(6.6)式(6.6)是平行投影的计算公式,写成齐次坐标表达式为:10001010001ddqqddxxzxyyyzzq (6.7)投影中心在无穷远处平行投影),(zyxComputer Graphics 6.1.3 任意坐标系到观察坐标系中的变换 v 灭点灭点:一组不平行于投影平面的平行线,经过透视投影后相交于一点,称为灭点。v 主灭点主灭点:如果这组平行线平行于坐标轴,这时的灭点称为主灭点,至多存在三个主灭点,分别对应于投影平面切割的坐标轴的数目。v 透视投影按主灭点的个数分为一点透视
7、一点透视、二点透二点透视视和三点透视三点透视。图6.7 一点透视图6.9 三点透视图6.8 两点透视Computer Graphics在坐标系oxyz中来讨论投影问题。确定一个投影面:一个参考点 和投影平面的法线方向 。还要指定 的方向,为此要给定一个向量 ,U在投影平面上的垂直投影所指的方向便是 轴的方向。取过 点沿N方向作的射线定为 轴 观察坐标系 的建立 o ox xy yz z图6.10 投影平面的指定NyOxzUoxyz)nnnzyxN,(,)uuuxyzUyoozoyo)(000,z,yxo Computer Graphics设 是点 在坐标系oxyz中的坐标,和 轴的单位方向向量
8、为 、和 ,那么从坐标系oxyz到的变换是 坐标变换公式oxoyozo000(,)xyz),(131211aaa),(232221aaa),(333231aaazyxo(6.8)011121321222303132330 xxxaaayaaayyzaaazz 设 、和 轴的单位方向向量分别为i,j,k。轴和N方向一致,故有zo 轴和向量UN方向一致,设xo其中x,y和z分别为ox,oy,oz轴的单位方向向量,则 轴的单位方向向量应是 和 轴的单位向量的向量积,因此yoxozoxoyozo313233222(,)(,)nnnnnnaaaxy zxyzkzyxzyxNU321bbbzyxzyxnn
9、nuuu232221321131211),(),(bbbbbbaaai212223133212331133133112311132(,)(,)aaaa aa aa aa aa aa ajComputer Graphics 齐次坐标形式在坐标系oxyz中给定的投影方向和视点的坐标都可用式(6.8)变换到坐标系 中的量 和 。zyxo),(dddzyx ),(ccczyx 式(6.8)写成齐次坐标表达式为 111213142122232431323334100011xaaaaxyaaaayzaaaaz (6.9)其中 41 0203 0(),1,2,3iiiiaa xa ya zi(6.8)011
10、121321222303132330 xxxaaayaaayyzaaazz Computer Graphics 坐标系oxyz中任一点(x,y,z)在投影平面上的投影把式(6.9)代入式(6.3)得110001000000343332312423222114131211zyxaaaaaaaaaaaazyzxzqyxcccccqq13433323134243323322231213414331332123111zyxazaaaayazayazayazayazaxazaxazaxazaxazccccccccccccccccc(6.10)坐标系oxyz中任一点(x,y,z),由(6.10)和(6.4
11、)便可求得它在投影平面上的投影点 。(,0)ppxy (6.4),pqpqxxqyyq平行投影时,由式(6.7)和(6.9),得 111213142122232431323334100010000110001ddqqddxaaaaxzxaaaayyyaaaazzq 1131123213331434213122322333243410001ddddddddddddddddxxxxaaaaaaaaxzzzzyyyyyaaaaaaaazzzzz (6.11)Computer Graphics 6.1.4射影变换 做三维裁剪或消除隐藏线时,可把一个对象的透视图看成另一个对象的在同一投影平面上的正视图,
12、并要求两个对象对应点坐标分量 的排序一致。后一个对象可以通过前一个对象做下述射影变换得到,zzzBzAzcpBzAzzzBzAzzzbbbcfffc)()(zzzxxxxccccp)(zzzyyyyccccp)(BzAzzBzAzzbbcffc)()(,cfbfbAzzz Bz z所以(6.12)(6.13)对于三维裁剪来说,希望变换 不改变三维窗口前后平面 =和 =的位置,这时式(4.16)中的A和B应取成zfzzbz代入投影平面透视投影平行投影图6.12 由透视投影变换到平行投影Computer Graphics变换为单调递增函数由上式求导得 为单调递增函数,只要 便是 的单调递增函数,可
13、保证两个对象对应点按坐标分量的排序是一致的。zzBzAzcp2)(zzBzAzdzdccpcczzBzA,0zpzpzbfbfczzBzzzA ,由得,bcfczzzz只要 则)(bcfcczzzzBzAcczzBzA,0Computer Graphics 射影变换的齐次坐标表示 联立式(6.2)和(6.12),则得到射影变换的齐次坐标表示 1100000000zyxzBAyzxzqzyxcccccqqq平行投影时,可直接取 zzp(6.14)式(6.6)和(6.14)就是在平行投影时所建立的一个仿射变换,变换的齐次坐标表示为:100010001010001ddppddpxzxxyyyzzzq
14、 (6.2)(6.12)zzzyyyyzzzxxxxccccpccccp)()(zzBzAzcp (6.6)zzyyyzzxxxddpddpComputer Graphics 世界坐标至规范化坐标空间的变换,就是要把世界坐标系中的图形变到规范化坐标系 中。这个变换把图6.13中的平行六面体P1P2P3P4Q1Q2Q3Q4变成图6.15中的单位立方体,把图6.14中的棱台P1P2P3P4Q1Q2Q3Q4变成图6.16的棱台。6.2 视见体到规范视见体的变换在规范化坐标系中定义了两种视见体:平行投影的视域由下列方程定义对透视来说,视见体是下列六个方程代表的平面围成的棱台vvvvzyxomin,y,
15、y,1,vvvvvvvvvvxzxzzzzzz 1 ,0 ,1 ,0 ,1 ,0vvvvvvzzyyxx图6.13 平行投影时定义的窗口P1P4P3P2Q2Q3Q4Q1A4A3A2A1图6.14 透视时定义的窗口CP1P2P3P4Q1Q2Q3Q4A4A3A2A1xvzvyv111ov图6.15 平行投影时的规范化空间yvxvzv图6.16 透视时的规范化空间ovComputer Graphics 6.2.1平行投影视见体的规范化设图Pi和Qi在世界坐标中的坐标为 。第一步要把点P1移到坐标原点,这个变换的矩阵为 经变换TR后,平行六面体在 和 平面上的投影为图6.17所示4 ,3 ,2 ,1
16、),(),(iyxQyxPiiiiii1111 ,yybxxbyx 1111000100010001RxyzT T图6.17 平行六面体在两个坐标平面上的投影zxozyo(a)bxby(b)xzzyComputer Graphics第二、三、四步变换第三步是长方体变为单位长的立方体。这个变换矩阵为111110001000100001xyHbzzbzzS S 10000)(0000)(0000)(1111121231zzyyxxS S第二步对平行六面体做切变,使它成为一个长方体。这个切变的矩阵为第四步为把 z 轴反向,变换矩阵为10000100001000012S S由坐标系 到规范化坐标系的变
17、换为TRHTvvvzyxzyx)1,()1,(12TSSSzyxo(a)bxby(b)xzzyComputer Graphics 6.2.2透视投影视见体的规范化 变换后,棱台在 和 平面上的投影如上图所示。2)把经过 变换后的棱台变成正棱台,其变换为zxozyoTR1)把视点移至坐标原点,变换为3)进行单位化,变换矩阵为 10000)(0000)(0000)(111121231czzyyxxS S4)变换为把z轴反向,变换也是S2。从坐标 变到坐标 的变换为zyxovvvvzyxo1000100010001cccRzyxT41121121002()20102()00100001cccHcxx
18、xzzyyyzzSTRHTvvvzyxzyx)1,()1,(12TSSS4Computer Graphics 6.3 用三维规范体裁剪 在规范化坐标系中平行投影时,视见体是由方程x=0,x=1,y=0,y=1,z=0和z=1代表的六个平面围成的立方体。透视时的视见体是棱台,由方程x=z,x=z,y=z,y=z,z=zmin和z=1代表的六个平面围成图6.19 两种视见体Computer Graphics SutherlandCohen 算法推广到三维判断显然不可见的线段的编码应为六位,这六位的安排是点在视见体左面,第1位为1,x0,(x1,(xz)点在视见体下面,第3位为1,y0,(y1,(y
19、z)点在视见体后面,第5位为1,z1,(z1)点在视见体前面,第6位为1,z0,(zzmin)括号中的条件适用于透视的情况。Computer Graphics 直线和视见体的边界面的交点设线段的起点和终点:P1(x1,y1,z1)和P2(x2,y2,z2),直线方程为 x=x1+(x2x1)t,y=y1+(y2y1)t,z=z1+(z2z1)t和视见体的边界面,例如y=1求交时,把tL代入即可求得交点的坐标。求P1P2和平面x=-z的交点时,把直线方程代入x=-z中求得交点处的参数121(1)/()Ltyyy)()(121211zzxxxztL121()()iiiiPAtPPNNCompute
20、r Graphics梁友栋Barsky 算法推广到三维当视见体为立方体时,其推广是直接的。当视见体为棱台时,设121212,zzzyyyxxx相应平面与线段的参数值为 BAFTBRLkrstkkk,/则:min1vvvvvvvvvvvxzxzyzyzzzz 111111111min11LRBTFBAszxszxszyszyszzsz()()LRBTFBArxzrxzryzryzrzrz ,Computer Graphicsbegin t0:=0;t1:=1;deltax:=x1x0;delatz:=z1z0;clipt(deltax,deltaz,x0+z0,t0,t1);clipt(delt
21、ax,deltaz,z0 x0,t0,t1);deltay:=y1y0;clipt(deltay,deltaz,y0+z0,t0,t1);clipt(deltay,deltaz,z0y0,t0,t1);clipt(deltaz,z0zmin,t0,t1);clipt(deltaz,1z0,t0,t1);x0:=x0+t0*deltax;y0:=y0+t0*deltay;z0:=z0+t0*deltaz;x1:=x0+t1*deltax;y1:=y0+t1*deltay;z1:=z0+t1*deltaz;showline(x0,y0,z0,x1,y1,z1);1:end clip的主体部分程序C
22、omputer Graphics窗口到视口(视区)的变换 窗口到视口(视区)的变换是指把所定义的视见体中的内容对应到二维的屏幕之中。相当于将相机拍摄的底片洗印到不同尺寸的相片上。通常视见体的宽高比和视口的宽高比应该相同,这样当视见体中的图形映射到视口时物体才不会发生变形。Computer Graphics 6.4 窗口到视口的变换 视口(区)是在屏幕或绘图纸上指定的一个矩形,在 坐标系中的顶点的坐标分别是(VL,VB)和(VR,VT)。窗口由点(WL,WB)和(WR,WT)决定。窗口中的图形应该成比例地变到视口。窗口中的任一点 和 视口中的对应点(xv,yv)应满足下列关系是vvvyxo整理得
23、图6.20 窗口至视口的变换wRwLwBwTvLvRvBvTxvOvyvywOwxw(,)ppxypLvLRLRLxwxvvvwwpBvBTBTBywyvvvwwvpvpxAxByCyD其中(6.15)LRLRwwvvALLwAvBBTBTwwvvCBBwCvDComputer Graphics6.4 窗口到视口的变换vvqvvvqvqyyqxx ,齐次坐标形式为 其中qyxDCBAqyxqqvvqvq10000(6.16)qpxx qqpyy q在OpenGL中可以用如下函数定义视口:void glViewport(GLint x,GLint y,GLsizei width,GLsizei
24、height);其中:x、y为视口矩形的左下角(像素为单位)坐标;width、height分别为视口的宽和高。默认情况下,初始视口的值为(0,0,winWidth,winHeight),其中winWidth、winHeight为窗口的宽和高。应该使视口区的长宽比与取景体的长宽比相等,否则会使显示的图象变形 vpvpxAxByCyDComputer Graphics窗口、视口变换窗口、视口变换v 修改视口:glViewport()是OpenGL提供的修改视口的函数。v 将glViewport(0,0,width,height)改为glViewport(0,0,width/2,height/2),
25、再执行程序,可以看到图形变小了一半。这是因为glViewport()指定了一个更小的显示区域(视口)。v 修改窗口(视见体):将gluOrtho2D(0,width,0,height)改为gluOrtho2D(0,2*width,0,2*height),再执行程序,可以看到图形同样减小了一半。虽然视区未变,但由于窗口(视见体)变大了,图形也就显得小了。Computer Graphics 投影平面上窗口的定义可以有两种方法。一种是OpenGL中采用的用glFrustum()、glPerspective()和glOrtho()定义四棱台或四棱柱的视见体,他们在投影平面上的投影自然形成了窗口。这种方
26、法虽然直观,但难以保证所观察的图形在窗口内,另一种自动定义窗口的方法。窗口的定义Computer Graphics 自动定义窗口 在对象的中心位置附近给定一点(xc,yc,zc)和一个常数r,要求以该点为球心,r为半径的球能把对象包含在内。定义立方体设点(xc,yc,zc)的投影为 ,令八个点投影到投影平面,设其投影点的坐标分别为 以 为左下角点,为右上角定义的窗口,常常不和预先由参数VL,VB,VR,VT定义的视口视口相似,须作调整,保证所观察的图形在窗口内,),(rzryrxccc8 ,2 ,1 ),(iyxii),(ccyxmax()max()micmicxxxyyy),(mcmcyyx
27、x),(mcmcyyxx:()/()/TBRLmmmmmmmmAVVVVif yAxthen xyAelse if yA xthen yxAComputer Graphics 6.5 连续变换的处理(6.17)(,1)(,1)TTx y zx y zT T1其中T1是一个44的矩阵。设投影变换是2(,)(,1)TTqqxy qx y zT T(6.18)其中T2是34矩阵,窗口至视区的变换是3(,)(,)TTvqvqvqqxyqxy qT T设在世界坐标系中的变换合并成一个矩阵T T1,变换为(6.19)其中T3是33矩阵。为了适合不同物理设备尺度的要求,在x和y方向还要分别乘以一常数,可由3
28、3的变换矩阵T4来实现,即4(,)(,)TTsqsqsvqvqvxyqxyqT T把变换(6.17)式至(6.20)式合并起来得4 3 2 1(,)(,1)(,1)TTTsqsqsxyqx y zx y zT T T TT T T TT T其中T=T4T3T2T1是一个34矩阵。(6.21)(6.20)Computer Graphics 屏幕坐标的计算 在对图形变换以前,先要算出T,输出每一个图形元素时,只要作一次矩阵向量乘法(6.21)式,然后求得屏幕坐标中点的坐标 如果不要作投影变换,例如显示对象本身是二维的,或是平行投影,那么式(6.22)也可不作投影变换,这时可直接令(6.22)ssq
29、sssqsqyyqxx,ssqssqxxyy(6.21)TTTssqsqzyxzyxqyx)1,()1,(),(1234TTTTTComputer Graphics 提高效率的技术图6.21 图形的显示流程对窗口剪 裁窗口至视口的变换显示或绘 图世界坐标系的三维变换投影从图6.21来看,在投影变换之后,窗口到视区变换之前还要对窗口作裁剪,裁剪工作无法用矩阵来表示,不能把裁剪工作合并到T中去。为减少工作量,可把几个矩阵合并起来GKS3D 图形显示流程Computer Graphics提高效率的技术 对三维窗口,窗口在深度方面有两个平行于投影面的平面作为裁剪的边界,这时可把深度裁剪放在最前面做,最
30、后作二维裁剪。简单的图形处理流程 T=T4T3T2T1Computer Graphics 6.6.1 OpenGL中的图形变换 v 模型变换 构造一个复杂的场景需要许多物体,这些物体都定义于其模型坐标系中,由于模型坐标系是依物体而建立的,物体在其中的表示相对简单。一个物体或者独立地出现在世界坐标系中,或者是更复杂物体的组成部分,无论哪种情况,都需要一个几何变换将其变换到新的坐标系中,这个变换称模型变换。if(c_mode=1)glTranslatef(2,0,-2);/平移 if(c_mode=2)glScalef(0.5,0.6,1.2);/放缩 if(c_mode=3)glRotatef(
31、30,0,1,0);/旋转 v 观察变换 在实际生活中,为了在不同的距离和角度上拍摄物体,我们可以移动物体,进行模型变换,也可以保持物体不动而移动照相机,这个变换就称为观察变换。gluLookAt(0,0,12,0,0,0,0,1,0);/设定观察点的位置 Computer Graphics gluLookAtv它共接受三组坐标,分别为eye,center,upeye表示我们眼睛在“世界坐标系”中的位置,center表示眼睛“看”的那个物体中心点的坐标,up表示观察者本身的方向,如果将观察点比喻成我们的眼睛,那么这个up则表示我们是正立还是倒立异或某一个角度在看,所看的影像大不相同,故此时需要
32、指明我们现在正立,那么X,Z轴为0,Y轴为正即可,通常将其设置为1,只要表示一个向上的向量(方向)即可Computer Graphics OpenGL中的图形变换v投影变换 投影变换定义了一个视见体,即限定场景在屏幕上显示的范围。glFrustum(-0.5,1,-0.5,1,1,20);/定义透视投影矩阵 glOrtho(-7,7,-7,7,2,12);/定义正交投影矩阵 Computer Graphicsv视口变换 视口变换是指把所定义的视见体中的内容对应到二维的屏幕之中。相当于将相机拍摄的照片洗印到不同尺寸的相片上。通常视见体的宽高比和视口的宽高比应该相同,这样当视见体中的图形映射到视口
33、时物体才不会发生变形。glViewport(0,0,cx,cy);/定义视口大小,cy为窗口的高度 Computer Graphics 6.6.2 OpenGL中的图形变换应用举例 例例1 以一立方体为例,投影模式采用透视,视点固定,对其作平移、放缩和旋转等模型变换,结果如图6.226.26所示。图 6.22 原点在初始位置(1,1,1)图 6.23 平移图6.24 放缩图6.25 绕y轴旋转图6.26 变换代替平移Computer Graphics 程序主要代码如下void CExam2View:OnDraw(CDC*pDC)CExam2Doc*pDoc=GetDocument();ASSE
34、RT_VALID(pDoc);/TODO:add draw code for native data hereglClearColor(1,1,1,1);/用白色清屏glClear(GL_COLOR_BUFFER_BIT);glLoadIdentity();/变换矩阵初始化gluLookAt(0,0,12,0,0,0,0,1,0);/设视点,(0,0,0)为参考点坐标,/gluLookAt(-2,0,14,-2,0,0,0,1,0);/观察变换替代平移变换的视点draw_coord();glPushMatrix();/把当前变换矩阵压入堆栈glTranslatef(1,1,1);/模型坐标系原
35、点变换到世界坐标系的(1,1,1)位置/在模型坐标系中做变换Computer Graphics if(c_mode=1)glTranslatef(2,0,-2);/平移 if(c_mode=2)glScalef(0.5,0.6,1.2);/缩放 if(c_mode=3)glRotatef(30,0,1,0);/旋转 /下面这一函数可以得到当前的模型变换矩阵 /glGetDoublev(GL_MODELVIEW_MATRIX,array);draw_cuboid(4,4,4);glPopMatrix();/从堆栈中恢复变换前的变换矩阵void CExam2View:OnSize(UINT nTy
36、pe,int cx,int cy)/窗口变化时执行该程序 CView:OnSize(nType,cx,cy);/窗口大小改变时的事件处理程序 /TODO:Add your message handler code here glMatrixMode(GL_PROJECTION);/选择当前矩阵为投影矩阵 glLoadIdentity();glFrustum(-0.5,1,-0.5,1,1,20);/定义窗口 glMatrixMode(GL_MODELVIEW);/选择当前矩阵为模型变换 glShadeModel(GL_FLAT);/设置明暗效果,GL-FLAT,一个面片的颜色一致,/GL-SM
37、OOTH,面片的颜色由插值产生 glViewport(0,0,cx,cy);/定义视口Computer Graphics绘制立方体void CExam2View:draw_cuboid(GLdouble a,GLdouble b,GLdouble c)/绘制立方体 glColor3f(0,0,0);glBegin(GL_LINE_LOOP);/后面 glVertex3f(0,0,0);glVertex3f(a,0,0);glVertex3f(a,b,0);glVertex3f(0,b,0);glEnd();glBegin(GL_LINE_LOOP);/前面 glVertex3f(0,0,c);
38、glVertex3f(a,0,c);glVertex3f(a,b,c);glVertex3f(0,b,c);glEnd();glBegin(GL_LINES);/点按照线段连接glVertex3f(0,0,0);glVertex3f(0,0,c);glVertex3f(a,0,0);glVertex3f(a,0,c);glVertex3f(a,b,0);glVertex3f(a,b,c);glVertex3f(0,b,0);glVertex3f(0,b,c);glEnd();Computer Graphics 绘制坐标系void CExam2View:draw_coord()/绘制坐标系glC
39、olor3f(1,0,0);glEnable(GL_LINE_STIPPLE);/线型设置glLineStipple(1,0 xF0F0);/虚线glBegin(GL_LINES);glVertex3f(0,0,0);glVertex3f(7,0,0);glVertex3f(0,0,0);glVertex3f(0,7,0);glVertex3f(0,0,0);glVertex3f(0,0,7);glEnd();glDisable(GL_LINE_STIPPLE);Computer Graphicsvoid CExam2View:OnRotate()/TODO:Add your command
40、handler code herec_mode=3;Invalidate();/激活OnDrawvoid CExam2View:OnTranslate()/TODO:Add your command handler code herec_mode=1;Invalidate();void CExam2View:OnScale()/TODO:Add your command handler code herec_mode=2;Invalidate();void CExam2View:OnInicube()/TODO:Add your command handler code herec_mode=
41、0;Invalidate();Computer Graphics 如果保持物体不动,移动视点可以得到同样的视觉效果。例如,对于平移变换glTranslatef(2,0,-2)的效果图6.23,也可以通过观察变换来实现,只需把gluLookAt(0,0,12,0,0,0,0,1,0)改为gluLookAt(-2,0,14,-2,0,0,0,1,0)即可,结果如图6.26所示。我们可以用函数glGetDoublev(GL_MODELVIEW_MATRIX,array)得到当前的模型变换矩阵。可以知道,视点固定gluLookAt(0,0,12,0,0,0,0,1,0),作glTranslatef(2
42、,0,-2)平移变换后的模型变换矩阵与不作此平移,而是作观察变换gluLookAt(-2,0,14,-2,0,0,0,1,0)的模型变换矩阵是一样的,此时1.00 0.00 0.003.000.00 1.00 0.001.000.00 0.00 1.0013.000.00 0.00 0.001.00array(6.20)图6.26 变换代替平移 移动视点可得到同样的效果Computer Graphics 例 2 仍以上述立方体为例,看一下正投影与透视以及裁剪的效果。对例1程序代码做一些修改即可,执行结果如图6.276.29所示。图 6.27 平行投影图6.28透视投影图6.29 裁剪Compu
43、ter Graphics 修改部分代码如下:void CExam3View:OnDraw(CDC*pDC)CExam3Doc*pDoc=GetDocument();ASSERT_VALID(pDoc);/TODO:add draw code for native data hereCRect rc;GetClientRect(&rc);/得到视区的大小OnSize(SIZE_RESTORED,rc.right,rc.bottom);/把rc传到OnSizeglClearColor(1,1,1,1);glClear(GL_COLOR_BUFFER_BIT);glLoadIdentity();/变
44、换矩阵初始化gluLookAt(6,5.5,7,0,0,0,0,0,1);glColor3f(1,0,0);draw_coord();draw_cuboid(3,3,3);例2程序代码Computer Graphicsvoid CExam3View:OnSize(UINT nType,int cx,int cy)CView:OnSize(nType,cx,cy);/TODO:Add your message handler code hereglMatrixMode(GL_PROJECTION);/选择当前矩阵为投影矩阵glLoadIdentity();if(p_mode=0)glFrustum(-3,5,-3,5,5,20);/透视,不裁剪/glFrustum(-3,5,-3,5,6,20);/由于近平面而裁剪if(p_mode=1)glOrtho(-7,7,-7,7,2,12);/平行glMatrixMode(GL_MODELVIEW);/选择当前矩阵模型变换矩阵glShadeModel(GL_FLAT);glViewport(0,0,cx,cy);void CExam3View:OnFrustum()p_mode=0;Invalidate();void CExam3View:OnOrtho()p_mode=1;Invalidate();