习题7.1为什么需要隐藏面消隐算法?答:因为我们在用计算机生成三维物体的真实感图形,必须要做的是确定物体的可见部分,只有确定了物体的可见部分,我们才能在计算机中真实地再现三维物体。因此,我们就需要一个隐藏面消隐算法来去掉物体的不可见部分,从而避免错误地将不可见部分显示出来,这样就可以在计算机中生成一个三维物体的真实感图形了。7.2能否用多边形相邻两条边决定的向量积来确定内法线方向?为什么?答:可以。设多边形F的顶点为Lvvv,,,21,顶点的次序要求这样排列,使观察者在多面体外沿着Lvvvv321走时,多边形的内部始终在观察者的右侧。(定义110,vvvvLL)对顶点进行分类,分为凸点集合A和凹点集合B,对于点iv:如果属于集合A,则F的内法线方向定义为Livvvviiii1,11;如果属于集合B,则F的内法线方向定义为Livvvviiii1,11;7.3已知点)6,4,2(),20,6,3(),0,2,1(321PPP和一个视点)10,0,0(C,确定从C点观察时,哪个点遮挡了其它点。答:连接观察点)10,0,0(C和点)0,2,1(1P的直线是:,tx,2tytz1010为了判断)20,6,3(2P是否在这条直线上,可以将点带入方程,得3x时3t,在3t时20,6,3zyx,所以2P在过C点和1P点的投影线上。接着以C为基准,判断哪个点在前面。C,1P,2P分别在这条线的3,1,0t位置上。由t值可知,1P在2P前面,即1P遮挡了2P。现在判断)6,4,2(3P是否在这条线上。2x时10,4,2zyt。所以)6,4,2(3P不在这条投影线上,既没有遮挡1P、2P,也没有被1P、2P遮挡。7.4设投影中心为原点,构造一个由透视投影到平行投影的变换。此变换使得原物体平行投影在Oxy平面上和将原物体透视投影在规范化视见平面上产生的图像相同。答:原物体在平面)/(bcczzz上的透视投影是:0100000000000vvvzzzPer其中,)/(bcczzzv。点),,(zyxP在视见平面上的透视投影是:),,(vvvzzyzzxzP透视投影到平行投影变换pT为:010011100000000fffvvpzzzzzT这里,fzz是规范化前裁剪平面的位置。现在,对点),,(zyxP应用变换pT,得到点:))1(,,(ffvvzzzzzyzzxzQQ在Oxy平面上的平行投影为:)0,,(zyzzxzQvv所以Q和P产生相同的投影图像。而且,pT变换将以1,,,,zzzzyzyzxzxf和为边界的规范化透视视见体变换到以1,0,,,,zzzyzyzxzxvvvv为边界的长方体上。7.5如图7.14所示,如果视图平面法向量为(1,-2,-1),试写出它的一个显示排列。答:因为这种排列方式只有第一项和第八项是确定的,所以该排列为(1,*,*,*,*,*,*,6),其中*可以任意排列。7.6z缓冲器算法是怎么判断哪个面应消隐的?答:z缓冲器算法设置了一个二维数组,类似于帧缓冲器。但是z缓冲器存放的是每个象素点的深度值,而不是帧缓冲器中的颜色值。z缓冲器的初始值为某个大的数值,通常是后裁剪平面的距离。在判断像素),(yx上的哪个平面更靠近观察者时,就可以简单地比较z缓冲器中的深度值和当前平面的深度值。如果当前平面的值比z缓冲器中的值小(即距视点更近),则用新值替换原z缓冲器中的值,像素的颜色值也变成新平面的颜色值。7.7基本扫描线方法如何判断哪个面需要消隐?答:基本思想:从最上面的一条扫描线开始工作,向下对每一条扫描线进行处理。在处理当前扫描线时,开一个一维数组作为当前扫描线的Z-buffer。首先找出与当前扫描线相关的多边形,以及每个多边形中相关的边对。对每一个边对之间的小区间上的各象素,计算深度,并与Z-buffer中的值比较,找出各象素处可见平面,计算颜色,写帧缓存。对深度计算,采用增量算法。7.8编写一个程序实现7.5节中的油画家算法。答:Voidpaint(){//设多边形已保存在链表m_AllPoly中;//m_AllPoly定义:listPolygonm_AllPoly[800];inti,k,j,num;//i,k,j临时整形变量,num纪录链表m_AllPoly中多边形的个数;floatzmin;//临时变量,设置一个最小值;floattemp;//临时变量;booltag;intPriority//记录优先级的临时变量;//为临时变量赋初值zmin=-65536;tag=TRUE;Priority=1;//第一步:根据每个多边形顶点z坐标的极小值zmin的大小,按由小到大对它们做初步排序//利用冒泡排序for(j=1;j=num;j++){for(i=j;i=num;i++){if(zminm_AllPoly[i].zmin)//m_AllPoly[i].zmin为链表中第i个多边形z最小值{zmin=m_AllPoly[i].zmin;k=i;//纪录当前多边形;}//if}//fori//按照从小到大排序,找到第j个多边形m_AllPoly[k],将m_AllPoly[j]与//m_AllPoly[k]交换位置。temp=m_AllPoly[j];m_AllPoly[j]=m_AllPoly[k];m_AllPoly[k]=temp;}//forji=1;while(num1){//第二步:若链表中只有一个多边形,则算法结束。否则取表头多边形P(即m_AllPoly[1])。//首先,判断P的z的最大值是否比链表中任一多边形Q的z坐标值的最小值小。用布//尔变量tag作为标志。如果为TRUE,说明成立;否则不成立。while(i=num&&tag){if(m_AllPoly[1].zmax=m_AllPoly[i].zmin){tag=FALSE;k=i;//纪录不符合条件,导致tag变为FALSE的多边形。}i++;}//while(i=num&&tag)if(tag){//如果满足条件,则P不会遮挡其它多边形,为优先级最低的多边形,在链表中去除Pm_AllPoly[1].Priority=Priority;Priority++;//删除P,所有多边形前移;for(i=1;inum;i++)m_AllPoly[i]=m_AllPoly[i+1];num--;//链表中多边形个数减1;}//if(tag)else{//否则,看是否满足4项条件之一,仍然用tag作标志。tag=TURE;i=k;//从不满足条件的多边形开始判断while(i=num&&tag){if((OXYBoxIntersect(m_AllPoly[1],m_AllPoly[i]))&&(!(ViewFar(m_AllPoly[1],m_AllPoly[i])))&&(!(ViewNear(m_AllPoly[i],m_AllPoly[1])))&&(OXYIntersect(m_AllPoly[1],m_AllPoly[i]))){//4个条件//OXYBoxIntersect(P,Q)表示两个多边形P和Q在OXY平面投影边界盒相交;//(ViewFar(P,Q)表示P的各顶点均在Q的远离视点的一侧;//ViewNear(Q,P)表示Q的各顶点均在P的靠近视点的一侧;//OXYIntersect(P,Q)表示P和Q在OXY平面上的投影不相交。tag=FALSE;k=i;//纪录不符合条件的多边形。}//ifif(tag){//若所有Q都满足下面四项条件中的一项,则在链表中去除Pm_AllPoly[1].Priority=Priority;Priority++;//删除P,所有多边形前移;for(i=1;inum;i++)m_AllPoly[i]=m_AllPoly[i+1];num--;//链表中多边形个数减1;}//if(tag)else{//对不满足此四项条件中任何一个的Q,交换P和Qtemp=m_AllPoly[1];m_AllPoly[1]=m_AllPoly[k];m_AllPoly[k]=temp;}//else}//while(i=num&&tag)}//else}//while(num1)}//voidpaint()