您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 管理学资料 > 计算机图形学实验z-buffer算法
实验六9-7一、实验题目z-buffer算法的代表性案例是绘制三个相互交叉的红绿蓝条,如图9-85所示,请使用MFC编程实现。二、实验思想Z-Buffer算法建立两个缓冲器:深度缓冲器,用以存储图像空间中每一像素相应的深度值,初始化为最大深度值(zs坐标)。帧缓冲器,用以存储图像空间中的每个像素的颜色,初始化为屏幕的背景色。①帧缓冲器初始值置为背景色。②确定深度缓冲器的宽度、高度和初始深度。一般将初始深度置为最大深度值。③对于多边形表面中的每一像素(xs,ys),计算其深度值zs(xs,ys)。④将zs(xs,ys)与存储在z缓冲器中该位置的深度值zBuffer(xs,ys)进行比较。⑤如果zs(xs,ys)≤zBuffer(xs,ys),则将此像素的颜色写入帧缓冲器,且用z(xs,ys)重置zbuffer(xs,ys)。三、实验代码CZBuffer::~CZBuffer(){delete[]P;}voidCZBuffer::SetPoint(CPi3p[],intm){P=newCPi3[m];for(inti=0;im;i++){P[i]=p[i];}PNum=m;}voidCZBuffer::CreateBucket()//创建桶表{intyMin,yMax;yMin=yMax=P[0].y;for(inti=0;iPNum;i++)//查找多边形所覆盖的最小和最大扫描线{if(P[i].yyMin){yMin=P[i].y;//扫描线的最小值}if(P[i].yyMax){yMax=P[i].y;//扫描线的最大值}}for(inty=yMin;y=yMax;y++){if(yMin==y)//建立桶头结点{HeadB=newCBucket;//建立桶的头结点CurrentB=HeadB;//CurrentB为CBucket当前结点指针CurrentB-ScanLine=yMin;CurrentB-pET=NULL;//没有连接边链表CurrentB-next=NULL;}else//建立桶的其它结点{CurrentB-next=newCBucket;CurrentB=CurrentB-next;CurrentB-ScanLine=y;CurrentB-pET=NULL;CurrentB-next=NULL;}}}voidCZBuffer::CreateEdge()//创建边表{for(inti=0;iPNum;i++){CurrentB=HeadB;intj=(i+1)%PNum;//边的第二个顶点,P[i]和P[j]构成边if(P[i].yP[j].y)//边的终点比起点高{Edge=newCAET;Edge-x=P[i].x;//计算ET表的值Edge-yMax=P[j].y;Edge-k=(P[j].x-P[i].x)/(P[j].y-P[i].y);//代表1/kEdge-pb=P[i];//绑定顶点和颜色Edge-pe=P[j];Edge-next=NULL;while(CurrentB-ScanLine!=P[i].y)//在桶内寻找该边的yMin{CurrentB=CurrentB-next;//移到yMin所在的桶结点}}if(P[j].yP[i].y)//边的终点比起点低{Edge=newCAET;Edge-x=P[j].x;Edge-yMax=P[i].y;Edge-k=(P[i].x-P[j].x)/(P[i].y-P[j].y);Edge-pb=P[i];Edge-pe=P[j];Edge-next=NULL;while(CurrentB-ScanLine!=P[j].y){CurrentB=CurrentB-next;}}if(int(P[j].y)!=P[i].y){CurrentE=CurrentB-pET;if(CurrentE==NULL){CurrentE=Edge;CurrentB-pET=CurrentE;}else{while(CurrentE-next!=NULL){CurrentE=CurrentE-next;}CurrentE-next=Edge;}}}}voidCZBuffer::Gouraud(CDC*pDC)//填充多边形{doubleCurDeep=0.0;//当前扫描线的深度doubleDeepStep=0.0;//当前扫描线随着x增长的深度步长doubleA,B,C,D;//平面方程Ax+By+Cz+D=0的系数CVectorV21(P[1],P[2]),V10(P[0],P[1]);CVectorVN=V21*V10;A=VN.X();B=VN.Y();C=VN.Z();D=-A*P[1].x-B*P[1].y-C*P[1].z;DeepStep=-A/C;//计算直线deep增量步长CAET*T1,*T2;HeadE=NULL;for(CurrentB=HeadB;CurrentB!=NULL;CurrentB=CurrentB-next){for(CurrentE=CurrentB-pET;CurrentE!=NULL;CurrentE=CurrentE-next){Edge=newCAET;Edge-x=CurrentE-x;Edge-yMax=CurrentE-yMax;Edge-k=CurrentE-k;Edge-pb=CurrentE-pb;Edge-pe=CurrentE-pe;Edge-next=NULL;AddEt(Edge);}EtOrder();T1=HeadE;if(T1==NULL){return;}while(CurrentB-ScanLine=T1-yMax)//下闭上开{T1=T1-next;HeadE=T1;if(HeadE==NULL)return;}if(T1-next!=NULL){T2=T1;T1=T2-next;}while(T1!=NULL){if(CurrentB-ScanLine=T1-yMax)//下闭上开{T2-next=T1-next;T1=T2-next;}else{T2=T1;T1=T2-next;}}CRGBCa,Cb,Cf;//Ca、Cb代边上任意点的颜色,Cf代表面上任意点的颜色Ca=Interpolation(CurrentB-ScanLine,HeadE-pb.y,HeadE-pe.y,HeadE-pb.c,HeadE-pe.c);Cb=Interpolation(CurrentB-ScanLine,HeadE-next-pb.y,HeadE-next-pe.y,HeadE-next-pb.c,HeadE-next-pe.c);BOOLFlag=FALSE;doublexb,xe;//扫描线的起点和终点坐标for(T1=HeadE;T1!=NULL;T1=T1-next){if(Flag==FALSE){xb=T1-x;CurDeep=-(xb*A+CurrentB-ScanLine*B+D)/C;//z=-(Ax+By-D)/CFlag=TRUE;}else{xe=T1-x;for(doublex=xb;xxe;x++)//左闭右开{Cf=Interpolation(x,xb,xe,Ca,Cb);if(CurDeep=ZB[ROUND(x)+Width/2][CurrentB-ScanLine+Height/2])//如果新采样点的深度大于原采样点的深度{ZB[ROUND(x)+Width/2][CurrentB-ScanLine+Height/2]=CurDeep;//xy坐标与数组下标保持一致pDC-SetPixel(ROUND(x),CurrentB-ScanLine,RGB(Cf.red*255,Cf.green*255,Cf.blue*255));}CurDeep+=DeepStep;}Flag=FALSE;}}for(T1=HeadE;T1!=NULL;T1=T1-next)//边的连续性{T1-x=T1-x+T1-k;}}deleteHeadB;deleteHeadE;deleteCurrentE;deleteCurrentB;deleteEdge;}voidCZBuffer::AddEt(CAET*NewEdge)//合并ET表{CAET*CE;CE=HeadE;if(CE==NULL){HeadE=NewEdge;CE=HeadE;}else{while(CE-next!=NULL){CE=CE-next;}CE-next=NewEdge;}}voidCZBuffer::EtOrder()//边表的冒泡排序算法{CAET*T1,*T2;intCount=1;T1=HeadE;if(T1==NULL){return;}if(T1-next==NULL)//如果该ET表没有再连ET表{return;//桶结点只有一条边,不需要排序}while(T1-next!=NULL)//统计结点的个数{Count++;T1=T1-next;}for(inti=1;iCount;i++)//冒泡排序{T1=HeadE;if(T1-xT1-next-x)//按x由小到大排序{T2=T1-next;T1-next=T1-next-next;T2-next=T1;HeadE=T2;}else{if(T1-x==T1-next-x){if(T1-kT1-next-k)//按斜率由小到大排序{T2=T1-next;T1-next=T1-next-next;T2-next=T1;HeadE=T2;}}}T1=HeadE;while(T1-next-next!=NULL){T2=T1;T1=T1-next;if(T1-xT1-next-x)//按x由小到大排序{T2-next=T1-next;T1-next=T1-next-next;T2-next-next=T1;T1=T2-next;}else{if(T1-x==T1-next-x){if(T1-kT1-next-k)//按斜率由小到大排序{T2-next=T1-next;T1-next=T1-next-next;T2-next-next=T1;T1=T2-next;}}}}}}CRGBCZBuffer::Interpolation(doublet,doublet1,doublet2,CRGBc1,CRGBc2)//线性插值{CRGBc;c=(t-t2)/(t1-t2)*c1+(t-t1)/(t2-t1)*c2;returnc;}voidCZBuffer::InitDeepBuffer(intwidth,intheight,doubledepth)//初始化深度缓冲{Width=width,Height=height;ZB=newdouble*[Width];for(inti=0;iWidth;i++)ZB[i]=newdouble[Height];for(i=0;iWidth;i++)//初始化深度缓冲for(intj=0;jHeight;j++)ZB[i][j]=double(depth);}四、程序结果截图
本文标题:计算机图形学实验z-buffer算法
链接地址:https://www.777doc.com/doc-7318439 .html