计算机图形学实验zbuffer算法.docx
《计算机图形学实验zbuffer算法.docx》由会员分享,可在线阅读,更多相关《计算机图形学实验zbuffer算法.docx(12页珍藏版)》请在冰豆网上搜索。
计算机图形学实验zbuffer算法
计算机图形学实验z-buffer算法
实验六9-7
一、实验题目
z-buffer算法的代表性案例是绘制三个相互交叉的红绿蓝条,如图9-85所示,请使用MFC编程实现。
二、实验思想
Z-Buffer算法建立两个缓冲器:
深度缓冲器,用以存储图像空间中每一像素相应的深度值,初始化为最大深度值(zs坐标)。
帧缓冲器,用以存储图像空间中的每个像素的颜色,初始化为屏幕的背景色。
1帧缓冲器初始值置为背景色。
2确定深度缓冲器的宽度、高度和初始深度。
一般将初始深度置为最大深度值。
3对于多边形表面中的每一像素(xs,ys),计算其深度值zs(xs,ys)。
4将zs(xs,ys)与存储在z缓冲器中该位置的深度值zBuffer(xs,ys)进行比较。
5如果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;i{P[i]=p[i];}PNum=m;}voidCZBuffer::CreateBucket()//创建桶表{intyMin,yMax;yMin=yMax=P[0].y;for(inti=0;i{if(P[i].y{yMin=P[i].y;//扫描线的最小值}if(P[i].y>yMax){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;i{CurrentB=HeadB;intj=(i+1)%PNum;//边的第二个顶点,P[i]和P[j]构成边if(P[i].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].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;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;i{T1=HeadE;if(T1->x>T1->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->k>T1->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->x>T1->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->k>T1->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;iZB[i]=newdouble[Height];for(i=0;ifor(intj=0;jZB[i][j]=double(depth);}四、程序结果截图
P[i]=p[i];
PNum=m;
CreateBucket()//创建桶表
intyMin,yMax;
yMin=yMax=P[0].y;
for(inti=0;i{if(P[i].y{yMin=P[i].y;//扫描线的最小值}if(P[i].y>yMax){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;i{CurrentB=HeadB;intj=(i+1)%PNum;//边的第二个顶点,P[i]和P[j]构成边if(P[i].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].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;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;i{T1=HeadE;if(T1->x>T1->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->k>T1->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->x>T1->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->k>T1->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;iZB[i]=newdouble[Height];for(i=0;ifor(intj=0;jZB[i][j]=double(depth);}四、程序结果截图
if(P[i].y{yMin=P[i].y;//扫描线的最小值}if(P[i].y>yMax){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;i{CurrentB=HeadB;intj=(i+1)%PNum;//边的第二个顶点,P[i]和P[j]构成边if(P[i].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].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;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;i{T1=HeadE;if(T1->x>T1->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->k>T1->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->x>T1->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->k>T1->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;iZB[i]=newdouble[Height];for(i=0;ifor(intj=0;jZB[i][j]=double(depth);}四、程序结果截图
yMin=P[i].y;//扫描线的最小值
if(P[i].y>yMax)
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;
CreateEdge()//创建边表
for(inti=0;i{CurrentB=HeadB;intj=(i+1)%PNum;//边的第二个顶点,P[i]和P[j]构成边if(P[i].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].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;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;i{T1=HeadE;if(T1->x>T1->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->k>T1->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->x>T1->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->k>T1->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;iZB[i]=newdouble[Height];for(i=0;ifor(intj=0;jZB[i][j]=double(depth);}四、程序结果截图
CurrentB=HeadB;
intj=(i+1)%PNum;//边的第二个顶点,P[i]和P[j]构成边
if(P[i].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/k
Edge->pb=P[i];//绑定顶点和颜色
Edge->pe=P[j];
Edge->next=NULL;
while(CurrentB->ScanLine!
=P[i].y)//在桶内寻找该边的yMin
CurrentB=CurrentB->next;//移到yMin所在的桶结点
if(P[j].y
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];
=P[j].y)
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;
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->x=CurrentE->x;
Edge->yMax=CurrentE->yMax;
Edge->k=CurrentE->k;
Edge->pb=CurrentE->pb;
Edge->pe=CurrentE->pe;
AddEt(Edge);
EtOrder();
T1=HeadE;
if(T1==NULL)
return;
while(CurrentB->ScanLine>=T1->yMax)//下闭上开
T1=T1->next;
HeadE=T1;
if(HeadE==NULL)
if(T1->next!
T2=T1;
T1=T2->next;
while(T1!
if(CurrentB->ScanLine>=T1->yMax)//下闭上开
T2->next=T1->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)/C
Flag=TRUE;
xe=T1->x;
for(doublex=xb;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;i{T1=HeadE;if(T1->x>T1->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->k>T1->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->x>T1->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->k>T1->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;iZB[i]=newdouble[Height];for(i=0;ifor(intj=0;jZB[i][j]=double(depth);}四、程序结果截图
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;
=NULL;T1=T1->next)//边的连续性
T1->x=T1->x+T1->k;
deleteHeadB;
deleteHeadE;
deleteCurrentE;
deleteCurrentB;
deleteEdge;
AddEt(CAET*NewEdge)//合并ET表
CAET*CE;
CE=HeadE;
if(CE==NULL)
HeadE=NewEdge;
while(CE->next!
CE=CE->next;
CE->next=NewEdge;
EtOrder()//边表的冒泡排序算法
intCount=1;
if(T1->next==NULL)//如果该ET表没有再连ET表
return;//桶结点只有一条边,不需要排序
while(T1->next!
=NULL)//统计结点的个数
Count++;
for(inti=1;i{T1=HeadE;if(T1->x>T1->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->k>T1->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->x>T1->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->k>T1->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;iZB[i]=newdouble[Height];for(i=0;ifor(intj=0;jZB[i][j]=double(depth);}四、程序结果截图
if(T1->x>T1->next->x)//按x由小到大排序
T2=T1->next;
T1->next=T1->next->next;
T2->next=T1;
HeadE=T2;
if(T1->x==T1->next->x)
if(T1->k>T1->next->k)//按斜率由小到大排序
while(T1->next->next!
T2->next->next=T1;
CRGBCZBuffer:
Interpolation(doublet,doublet1,doublet2,CRGBc1,CRGBc2)//线性插值
CRGBc;
c=(t-t2)/(t1-t2)*c1+(t-t1)/(t2-t1)*c2;
returnc;
InitDeepBuffer(intwidth,intheight,doubledepth)//初始化深度缓冲
Width=width,Height=height;
ZB=newdouble*[Width];
for(inti=0;iZB[i]=newdouble[Height];for(i=0;ifor(intj=0;jZB[i][j]=double(depth);}四、程序结果截图
ZB[i]=newdouble[Height];
for(i=0;ifor(intj=0;jZB[i][j]=double(depth);}四、程序结果截图
for(intj=0;jZB[i][j]=double(depth);}四、程序结果截图
ZB[i][j]=double(depth);
四、程序结果截图
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1