实验三.docx
- 文档编号:25537783
- 上传时间:2023-06-09
- 格式:DOCX
- 页数:21
- 大小:197.29KB
实验三.docx
《实验三.docx》由会员分享,可在线阅读,更多相关《实验三.docx(21页珍藏版)》请在冰豆网上搜索。
实验三
计算机科学系实验报告(首页)
课程名称
计算机图形学
班级
实验名称
消隐
教导教师
姓名
学号
日期
一、实验目的
掌握z缓冲算法。
二、实验设备与环境
TC2.0,WindowsXP
三、实验内容、程序清单及运行结果
1.创建应用程序框架,建立工程名称为Z_BufferEli的单文档应用程序框架
2.点击File->New->C/C++HeaderFile,之后输入文件名MyFace,定义MyFace.h文件,该文件主要定义三个用于处理点,线,面的类。
////////////////////////////////点类
classDPoint
{
public:
DPoint(){x=0;y=0;z=0;}//默认构造函数
DPoint(inta,intb,intc):
x(a),y(b),z(c){}//构造函数
DPoint(constDPoint&p):
x(p.x),y(p.y),z(p.z){}//复制构造函数
DPoint&operator=(constDPoint&rhs)//赋值操作
{
x=rhs.x;y=rhs.y;z=rhs.z;
return*this;
}
friendinlineintoperator==(constDPoint&p1,constDPoint&p2)//判断点是否相等,是返回1,否则返回0
{
if(p1.x==p2.x&&p1.y==p2.y&&p1.z==p2.z)
{
return1;
}
else
return0;
}
friendinlineintoperator!
=(constDPoint&p1,constDPoint&p2)//判断点是否不相等,是返回0,否则返回1
{
if((p1.x!
=p2.x)||(p1.y!
=p2.y)||(p1.z!
=p2.z))
{
return1;
}
else
return0;
}
voidsetx(inta)
{
x=a;
}
voidsety(intb)
{
y=b;
}
voidsetz(intc)
{
z=c;
}
intgetx()
{
returnx;
}
intgety()
{
returny;
}
intgetz()
{
returnz;
}
protected:
public:
intx;
inty;
intz;
};
/////////////////////////////////////////////线类
classDLine
{
public:
DLine(inta,intb,intc,intd,inte,intf):
p1(a,b,c),p2(d,e,f){}//构造函数
DLine():
p1(0,0,0),p2(0,0,0){}//默认构造函数
DLine(DPointx,DPointy):
p1(x),p2(y){}
DPointgetp1()
{
returnp1;
}
DPointgetp2()
{
returnp2;
}
DLine(constDLine&l)//复制构造函数
{
p1=l.p1;
p2=l.p2;
}
DLine&operator=(constDLine&rhs)//赋值操作
{
p1=rhs.p1;p2=rhs.p2;
return*this;
}
friendintintersect(constDLine&l1,constDLine&l2)//判断线段是否有公共点,有返回1,否则返回0
{
if((l1.p1==l2.p1)||(l1.p1==l2.p2)||(l1.p2==l2.p1)||(l1.p2==l2.p2))
{
return1;
}
else
return0;
}
protected:
private:
DPointp1;
DPointp2;
};
////////////////////////////面类
classDFace
{
public:
DFace():
p1(0,0,0),p2(0,0,0),p3(0,0,0),p4(0,0,0),L1(0,0,0,0,0,0),L2(0,0,0,0,0,0),L3(0,0,0,0,0,0),L4(0,0,0,0,0,0),a(0),b(0),c(0),d(0)
{
//a=b=c=d=0;
}//默认构造函数
DFace(DPointx,DPointy,DPointz,DPointw):
p1(x),p2(y),p3(z),p4(w),L1(x,y),L2(y,z),L3(z,w),L4(w,x)//构造函数
{
intx1=x.getx(),y1=x.gety(),z1=x.getz();
intx2=y.getx(),y2=y.gety(),z2=y.getz();
intx3=z.getx(),y3=z.gety(),z3=z.getz();
intx4=w.getx(),y4=w.gety(),z4=w.getz();
a=(int)((y1-y2)*(z1+z2)+(y2-y3)*(z2+z3)+(y3-y4)*(z3+z4)+(y4-y1)*(z4+z1));
b=(int)((z1-z2)*(x1+x2)+(z2-z3)*(x2+x3)+(z3-z4)*(x3+x4)+(z4-z1)*(x4+x1));
c=(int)((x1-x2)*(y1+y2)+(x2-x3)*(y2+y3)+(x3-x4)*(y3+y4)+(x4-x1)*(y4+y1));
d=(int)(-(a*x1+b*y1+c*z1));
}
intgeta()
{
returna;
}
intgetb()
{
returnb;
}
intgetcc()
{
returnc;
}
intgetd()
{
returnd;
}
private:
DPointp1,p2,p3,p4;
DLineL1,L2,L3,L4;
inta;
intb;
intc;
intd;
};
3.用2的方法创建Matrix.h文件,用于矩阵处理以及计算。
classMatrix
{
public:
intROW;//行数
intCOL;//列数
double**p;
public:
Matrix(intm=0,intn=0,double*A=NULL,intk=0)//;//矩阵的构造函数
{
ROW=m;//指定行数
COL=n;//指定列数
p=newdouble*[ROW];//生成元素为指针,长度为ROW的数组
for(inti=0;i { p[i]=newdouble[COL];//p[i]是长度为COL的数组的指针 for(intj=0;j { p[i][j]=A[i*n+j];//用一维数组构造二维数 } } } ~Matrix()//;//矩阵的析构函数 { for(inti=0;i { delete[]p[i];//释放数组 } } Matrix&operator=(Matrix&s)//;//赋值运算符重载 { ROW=s.ROW; COL=s.COL; p=newdouble*[ROW];//生成元素为指针,长度为ROW的数组 for(inti=0;i { p[i]=newdouble[COL];//p[i]是长度为COL的数组的指针 for(intj=0;j { p[i][j]=s.p[i][j];//用一维数组构造二维数 } } return*this; } Matrix&operator*(Matrix&t)//;//用友元声明乘法运算符重载 { intm=ROW,n=COL,k=t.COL; Matrixresult; result.ROW=m;result.COL=k; result.p=newdouble*[m]; for(inti=0;i { result.p[i]=newdouble[k]; for(intj=0;j { result.p[i][j]=0; for(intl=0;l result.p[i][j]+=p[i][l]*t.p[l][j]; } } ROW=result.ROW;COL=result.COL; for(i=0;i { for(intj=0;j { p[i][j]=result.p[i][j]; } } return*this; } }; 4.添加类CZ_BufferElilView的公有成员变量和成员函数。 classCZ_BufferEliView: publicCView {//…………………… //定义变量和函数 public: intn; intnum[1000]; COLORREFcolor[400][400];//帧缓存 doublez_distance[400][400];//z缓存 floatangle;//旋转角度 DPointP1,P2,P3,P4,P5,P6,P7,P8;//立方体的八个顶点 intIsInSide(CPointPx,CPointP1,CPointP2,CPointP3,CPointP4);//判断一个点是否在多边形内 voidFaceBuffer(DPointP1,DPointP2,DPointP3,DPointP4,COLORREFm_clr,CDC*pDC); //…………….. } 5.应用MFCClasswizard添加视图类CZ_BufferElilView的消息映射WM_KEYDOWN,其对应的消息映射函数如下: voidOnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags); 6.在Z_BufferElilView.cpp中添加程序结构代码。 1)添加头文件 //#include"MyFace.h" #include"Matrix.h" 2)CZ_BufferEliView的构造函数中对变量进行初始化。 CZ_BufferEliView: : CZ_BufferEliView(): P1(-100,100,100),P2(100,100,100),P3(100,100,-100),P4(-100,100,-100),P5(-100,-100,100),P6(100,-100,100),P7(100,-100,-100),P8(100,-100,-100) { //初始化帧缓存和Z缓存 angle=float(3.1415926/3); for(inti=0;i<400;i++) { for(intj=0;j<400;++j) { color[i][j]=RGB(255,255,255);// z_distance[i][j]=-1000; } } n=0; } 3)断一个点是否在多边形内部的函数。 intCZ_BufferEliView: : IsInSide(CPointPx,CPointP1,CPointP2,CPointP3,CPointP4) { doublea1,b1,a2,b2,a3,b3,a4,b4; intm=0;intx=(P1.x+P3.x)/2,y=(P1.y+P3.y)/2;//P1P3中点坐标 if((P1.x! =P2.x)&&(P1.x! =P4.x)) { a1=((double)(P2.y-P1.y))/(P2.x-P1.x);//P1P2斜率 b1=P1.y-a1*P1.x;//P1P2截距 a2=((double)(P3.y-P2.y))/(P3.x-P2.x); b2=P2.y-a2*P2.x; a3=a1; b3=P3.y-a1*P3.x; a4=a2; b4=P1.y-a4*P1.x; if(((a1*Px.x+b1-Px.y)*(a1*x+b1-y)>0)&&((a3*Px.x+b3-Px.y)*(a3*x+b3-y)>0)&&((a2*Px.x+b2-Px.y)*(a2*x+b2-y)>0)&&((a4*Px.x+b4-Px.y)*(a4*x+b4-y)>0)) { m++; } } elseif(P1.x==P2.x)//水平边的处理 { a2=((double)(P3.y-P2.y))/(P3.x-P2.x); b2=P2.y-a2*P2.x; a4=a2; b4=P1.y-a4*P1.x; if(P4.x>P1.x) { if(((a2*x+b2-y)*(a2*Px.x+b2-Px.y)>0)&&((a4*x+b4-y)*(a4*Px.x+b4-Px.y)>0)&&(P1.x { m++; } } else { if(((a2*x+b2-y)*(a2*Px.x+b2-Px.y)>0)&&((a4*x+b4-y)*(a4*Px.x+b4-Px.y)>0)&&(P4.x { m++; } } } elseif(P1.x==P4.x)//水平边的处理 { a1=((double)(P2.y-P1.y))/(P2.x-P1.x); b1=P1.y-a1*P1.x; a3=a1; b3=P3.y-a1*P3.x; if(P2.x>P1.x) { if(((a1*x+b1-y)*(a1*Px.x+b1-Px.y)>0)&&((a3*x+b3-y)*(a3*Px.x+b3-Px.y)>0)&&(P1.x { m++; } } else { if(((a1*x+b1-y)*(a1*Px.x+b1-Px.y)>0)&&((a3*x+b3-y)*(a3*Px.x+b3-Px.y)>0)&&(P2.x { m++; } } } returnm; } 4)对单个面的Z缓冲处理函数 voidCZ_BufferEliView: : FaceBuffer(DPointP1,DPointP2,DPointP3,DPointP4,COLORREFm_clr,CDC*pDC) { CPointp[4];intxleft,xright,ytop,ybottom; DFacef(P1,P2,P3,P4); inta=f.geta(),b=f.getb(),c=f.getcc(),d=f.getd(); p[0].x=P1.getx();p[0].y=P1.gety(); p[1].x=P2.getx();p[1].y=P2.gety(); p[2].x=P3.getx();p[2].y=P3.gety(); p[3].x=P4.getx();p[3].y=P4.gety(); //确定平面的X,Y范围 xleft=xright=p[0].x;ytop=ybottom=p[0].y; for(inti=0;i<4;++i) { if(p[i].x { xleft=p[i].x; } if(p[i].x>xright) { xright=p[i].x; } if(p[i].y { ybottom=p[i].y; } if(p[i].y>ytop) { ytop=p[i].y; } } //对XY范围内的点逐个判断是否在多边形内 for(inty=ybottom;y<=ytop;++y) { for(intx=xleft;x<=xright;++x) { CPointmid(x,y); if(IsInSide(mid,p[0],p[1],p[2],p[3])) { if(c! =0) { doublez=((double)(-d-a*x-b*y))/c; //z缓冲的过程 if(z>=z_distance[x+200][y+200]) { color[x+200][y+200]=m_clr; z_distance[x+200][y+200]=z; } } } } } } 5)OnDraw()函数中添加绘制图形的代码。 voidCZ_BufferEliView: : OnDraw(CDC*pDC) { CZ_BufferEliDoc*pDoc=GetDocument(); ASSERT_VALID(pDoc); pDC->TextOut(0,0,"按“X”、“Y”、“Z”键从各方位观看图形"); //TODO: Addyourmessagehandlercodehere CRectrect; GetClientRect(&rect); pDC->SetViewportOrg(rect.Width()/2,rect.Height()/2); //每次重绘前重新初始化帧缓存和Z缓存 for(inti=0;i<400;++i) { for(intj=0;j<400;++j) { color[i][j]=RGB(255,255,255); z_distance[i][j]=-1000; } } FaceBuffer(P1,P4,P3,P2,RGB(255,0,0),pDC); FaceBuffer(P5,P8,P7,P6,RGB(0,255,0),pDC); FaceBuffer(P1,P2,P6,P5,RGB(0,0,255),pDC); FaceBuffer(P4,P3,P7,P8,RGB(255,255,0),pDC); FaceBuffer(P1,P4,P8,P5,RGB(255,0,255),pDC); FaceBuffer(P2,P3,P7,P6,RGB(0,255,255),pDC); for(inty=-200;y<200;++y) { for(intx=-200;x<200;++x) { pDC->SetPixel(x,y,color[x+200][y+200]); } } P1=DPoint(-100,100,100);P2=DPoint(100,100,100); P3=DPoint(100,100,-100);P4=DPoint(-100,100,-100); P5=DPoint(-100,-100,100);P6=DPoint(100,-100,100); P7=DPoint(100,-100,-100);P8=DPoint(-100,-100,-100); } 6)通过按X,Y,Z键可以旋转立方体,从不同角度来观察。 voidCZ_BufferEliView: : OnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags) { doubleA[16]={1,0,0,0,0,cos(angle),-sin(angle),0,0,sin(angle),cos(angle),0,0,0,0,1}; MatrixRX(4,4,A,16); doubleB[16]={cos(angle),0,sin(angle),0,0,1,0,0,-sin(angle),0,cos(angle),0,0,0,0,1}; MatrixRY(4,4,B,16); doubleC[16]={cos(angle),-sin(angle),0,0,sin(angle),cos(angle),0,0,0,0,1,0,0,0,0,1}; MatrixRZ(4,4,C,16); doubleD[16]={1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}; MatrixM(4,4,D,16); switch(nChar){ case88: //按下X,Y,Z键图形绕三个轴旋转 num[n]=1; break; case89: num[n]=2; break; case90: num[n]=3; break; default: break; } //保证多次旋转仍能正确显示 for(intj=0;j<=n;++j) { if(num[j]==1) { M=RX*M; } if(num[j]==2) { M=RY*M; } if(num[j]==3) { M=RZ*M; } } n++; DPointp[8]; p[0]=P1;p[1]=P2;p[2]=P3;p[3]=P4; p[4]=P5;p[5]=P6;p[6]=P7;p[7]=P8; for(inti=0;i<8;++i) { doublex,y,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验