计算机图形学大作业课程设计 实验报告消隐算法.docx
- 文档编号:9244640
- 上传时间:2023-02-03
- 格式:DOCX
- 页数:16
- 大小:20.94KB
计算机图形学大作业课程设计 实验报告消隐算法.docx
《计算机图形学大作业课程设计 实验报告消隐算法.docx》由会员分享,可在线阅读,更多相关《计算机图形学大作业课程设计 实验报告消隐算法.docx(16页珍藏版)》请在冰豆网上搜索。
计算机图形学大作业课程设计实验报告消隐算法
安徽建筑工业学院
计算机图形学大作业
大作业名称:
消隐算法演示
院(系)名称:
专业:
班级:
姓名:
学号:
指导老师:
2011~2012年度第一学期
计算机图形学——消隐算法
1、设计目的:
通过检测可见面,消除隐藏线和隐藏面,以在二维平面上显示具有真实感图形。
消除隐藏线和隐藏面,是计算机图形学中比较因难但又是十分关键的一个问题。
消隐算法是决定相对于空间给定位置的观察者,哪些线、表面或物体是可见的,哪些是不可见的。
本章主要展示和计论一些最常用的隐藏线和隐藏面的消隐方法及技术。
2、设计思想:
投影变换失去了深度信息,往往导致图形的二义性,要消除二义性,就必须在绘制时消除被遮挡的不可见的线或面,习惯上称作消除隐藏线和隐藏面,简称为消隐。
经过消隐得到的投影图称为物体的真实图形。
●确定算法类
到目前为止,已经提出了很多有效的消隐算法,这些算法可以依据算法实现时所在的坐标系或空间进行分类,一般可分成两大类:
对象空间算法和图像空间算法。
本文采用的就是图像空间算法(image-spacemethods),这种方法是对投影平面或显示屏幕上的每一个像素位置逐点地检测其可见性。
这种算法比较粗糙.而且按图像空间算法得到的画面在放大后往往不能令人满意。
但这种算法计算效率比较高,因为在光栅扫描过程中可以充分利用画面的连贯性等性质。
●确定集体的实现算法
1.消除隐藏线
对造型的要求
在线框显示模型中,要求造型系统中有面的信息,最好有体的信息。
坐标变换
将视点变换到Z轴的正无穷大处,视线方向变为Z轴的负方向。
最基本的运算
判断面对线的遮挡关系.反复地进行线线、线面之间的求交运算
2.面消隐
面消隐算法的分类(图像空间的消隐算法,物体空间的消隐算法)
提高消隐算法效率的常见方法(利用连贯性,将透视投影转换成平行投影,包围盒技术,背面剔除,空间分割技术,物体分层表示)
本文是利用Z-Buffer算法的思想运用几何知识实现的,称为Z-Buffer算法的改进算法。
3、设计过程:
Z-Buffer算法的思想:
先将Z缓冲器中个单元的初始值置为最小值。
当要改变某个像素的颜色值时,首先检查当前多边形的深度值是否大于该像素原来的深度值(保存在该像素所对应的Z缓冲器的单元中),如果大于,说明当前多边形更靠近观察点,用它的颜色替换像素原来的颜色;否则说明在当前像素处,当前多边形被前面所绘制的多边形遮挡了,是不可见的,像素的颜色值不改变。
改进法:
通过记录投影与当前扫描线相交的多边形。
1.求点的平行投影和透视投影坐标值
2.用三维点坐标直接从当前点画线到某点
3.三维坐标下直接将当前点移动到某点
4.表面三个顶点调用求该表面的法矢
5.求观察方向矢量与表面法矢的数量积
6.画出立体上的平面并绘出消隐立体图
4、设计总结:
选择不同的消隐算法
消隐问题有不同的算法,有些算法要求速度快,有些要求图形的真实度高。
例如,快速消隐算法可用于实时模拟如飞行模拟等;具有高度真实感图形的消隐算法可用于计算机动画等领域,所生成的图形一般具有连续色调,并能产生阴影、透明、表面纹理及反射、折射等视觉效果。
不过这类算法比较慢。
产生一幅图可能需要几分钟甚至几小时。
所以,在进行消隐算法的设计时,应在计算速度和图形细节之间进行权衡,任何一种算法都不能兼顾两者。
消隐算法的实现空间
消隐算法可以在物体空间或图像空间中实现。
物体空间算法是在定义物体的坐标系中实现的,而图像空间算法是在对象显示的屏幕坐标系中实现的。
物体空间算法以尽可能高的精度完成几何计算,所以可以把图像放大许多倍而不致损害其准确性,但是图像空间算法只能以与显示屏的分辨率相适应的精度来完成计算,所以其图像的放大效果较差。
这两类算法的性能特性也是不同的。
物体空间算法所需的计算时间随场量中物体的个数而增加,而图像空间的计算时间则随图像中可见部分的复杂程度而增加。
5、设计平台:
Computer(Windowsxp),VC++
6、附件:
voidCMyView:
:
Project(floatX,floatY,floatZ)//此函数求点的平行投影和透视投影坐标值
{
XObs=-X*Aux1+Y*Aux3;
YObs=-X*Aux5-Y*Aux6+Z*Aux4;
//求透视投影坐标值
ZObs=-X*Aux7-Y*Aux8-Z*Aux2+Rol;
XProj=DE*XObs/ZObs;
YProj=DE*YObs/ZObs;
}
/////////////////////////////////////////////////////////////////////////////
voidCMyView:
:
WLineTo(floatX,floatY,floatZ,CDC*pDC)//用三维点坐标直接从当前点画线到一点的函数
{
Project(X,Y,Z);//将三维点作投影
XScreen=floor(0.5+XProj*Scale+150);//圆整
YScreen=floor(0.5+100-YProj);//圆整
pDC->LineTo(XScreen,YScreen);//画线到一点
}
/////////////////////////////////////////////////////////////////////////////
voidCMyView:
:
WMoveTo(floatX,floatY,floatZ,CDC*pDC)//三维坐标下直接将当前点移动到某点的函数
{
Project(X,Y,Z);//将三维点作投影
XScreen=floor(0.5+XProj*Scale+150);//圆整
YScreen=floor(0.5+100-YProj);//圆整
pDC->MoveTo(XScreen,YScreen);//移动到某点
}
/////////////////////////////////////////////////////////////////////////////
voidCMyView:
:
ReadVertics()//此函数用来给数组St的元素赋顶点坐标值
{
St[1][1]=40;St[1][2]=154;St[1][3]=-20;
St[2][1]=40;St[2][2]=154;St[2][3]=0;
St[3][1]=40;St[3][2]=46;St[3][3]=0;
St[4][1]=40;St[4][2]=46;St[4][3]=-20;
St[5][1]=-40;St[5][2]=46;St[5][3]=-20;
St[6][1]=-40;St[6][2]=154;St[6][3]=-20;
St[7][1]=-40;St[7][2]=154;St[7][3]=0;
St[8][1]=0;St[8][2]=134;St[8][3]=40;
St[9][1]=0;St[9][2]=66;St[9][3]=40;
St[10][1]=-40;St[10][2]=46;St[10][3]=0;
}
/////////////////////////////////////////////////////////////////////////////
voidCMyView:
:
ReadFaces()//此函数给数组Fc的元素赋表面有关的数据值
{
NF=9;
Fc[1][0]=4;Fc[1][1]=1;Fc[1][2]=2;Fc[1][3]=3;Fc[1][4]=4;
Fc[2][0]=4;Fc[2][1]=1;Fc[2][2]=6;Fc[2][3]=7;Fc[2][4]=2;
Fc[3][0]=3;Fc[3][1]=2;Fc[3][2]=7;Fc[3][3]=8;
Fc[4][0]=4;Fc[4][1]=2;Fc[4][2]=8;Fc[4][3]=9;Fc[4][4]=3;
Fc[5][0]=4;Fc[5][1]=1;Fc[5][2]=4;Fc[5][3]=5;Fc[5][4]=6;
Fc[6][0]=4;Fc[6][1]=7;Fc[6][2]=10;Fc[6][3]=9;Fc[6][4]=8;
Fc[7][0]=3;Fc[7][1]=3;Fc[7][2]=9;Fc[7][3]=10;
Fc[8][0]=4;Fc[8][1]=10;Fc[8][2]=5;Fc[8][3]=4;Fc[8][4]=3;
Fc[9][0]=4;Fc[9][1]=5;Fc[9][2]=10;Fc[9][3]=7;Fc[9][4]=6;
}
/////////////////////////////////////////////////////////////////////////////
voidCMyView:
:
VisionVector(intSt1)/*该函数用于求观察方向矢量St1isthefirstpointofaface.*/
{
v1=O1-St[St1][1];
v2=O2-St[St1][2];
v3=O3-St[St1][3];
}
/////////////////////////////////////////////////////////////////////////////
voidCMyView:
:
NormalVector(intSt1,intSt2,intSt3)//此函数用表面三个顶点调用求该表面的法矢
{
floatP1,P2,P3,Q1,Q2,Q3;
P1=St[St2][1]-St[St1][1];//求一个向量
P2=St[St2][2]-St[St1][2];
P3=St[St2][3]-St[St1][3];
Q1=St[St3][1]-St[St1][1];//求另一个向量
Q2=St[St3][2]-St[St1][2];
Q3=St[St3][3]-St[St1][3];
n1=P2*Q3-Q2*P3;//用向量积求法向量
n2=P3*Q1-Q3*P1;
n3=P1*Q2-Q1*P2;
}
/////////////////////////////////////////////////////////////////////////////
floatCMyView:
:
ScaleProduct(floatv1,floatv2,floatv3,
floatn1,floatn2,floatn3)//此函数用于求观察方向矢量与表面法矢的数量积
{
floatSProduct;
SProduct=v1*n1+v2*n2+v3*n3;
return(SProduct);
}
/////////////////////////////////////////////////////////////////////////////
voidCMyView:
:
DrawFace(CDC*pDC)//画出立体上的平面
{
intS,NS,No;
floatX,Y,Z,X0,Y0,Z0;
NS=Fc[F][0];
for(S=1;S<=NS;S++)
{
No=Fc[F][S];
X=St[No][1];
Y=St[No][2];
Z=St[No][3];
if(S==1){
WMoveTo(X,Y,Z,pDC);
X0=X;
Y0=Y;
Z0=Z;
}
elseWLineTo(X,Y,Z,pDC);
}
WLineTo(X0,Y0,Z0,pDC);
}
/////////////////////////////////////////////////////////////////////////////
voidCMyView:
:
DrawObject()//此函数用于绘出消隐立体图
{intSt1,St2,St3;
CDC*pDC=GetDC();
CPenpen1(PS_SOLID,1,(COLORREF)1),pen2(PS_DOT,1,(COLORREF)1);
CPen*pOldPen=pDC->SelectObject(&pen1);
for(F=1;F<=NF;F++)
{
St1=Fc[F][1];St2=Fc[F][2];St3=Fc[F][3];
VisionVector(St1);//求观察方向矢量
NormalVector(St1,St2,St3);//求表面法矢
if(ScaleProduct(v1,v2,v3,n1,n2,n3)>0)//判断数量积正否
{
pDC->SelectObject(&pen1);
DrawFace(pDC);//数量积大于零,表面可见,画出此表面
}
else;
}
pDC->SelectObject(pOldPen);
ReleaseDC(pDC);
}
/////////////////////////////////////////////////////////////////////////////
voidCMyView:
:
VisionPoint()//此函数用于给出视点位置
{//投影时初始值即正弦值和余弦值及其乘积的计算、赋值
floatTh,Ph;
Th=3.1415926*Theta/180;
Ph=3.1415926*Phi/180;
Aux1=sin(Th);
Aux2=sin(Ph);
Aux3=cos(Th);
Aux4=cos(Ph);
Aux5=Aux3*Aux2;
Aux6=Aux1*Aux2;
Aux7=Aux3*Aux4;
Aux8=Aux1*Aux4;
O1=Rol*Aux7;//给出视点位置
O2=Rol*Aux8;
O3=Rol*Aux2;
}
/////////////////////////////////////////////////////////////////////////////
voidCMyView:
:
Mydraw()
{
RedrawWindow();
ReadVertics();
ReadFaces();
//绘出透视投影下的凸多面体图形
VisionPoint();//给出视点位置
DrawObject();//画出立体的图形
}
/////////////////////////////////////////////////////////////////////////////
voidCMyView:
:
OnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags)
{//此函数用来利用上下左右键移动视点角度位置
switch(nChar){
caseVK_UP:
Phi=Phi-IncAng;
Mydraw();
break;
caseVK_DOWN:
Phi=Phi+IncAng;
Mydraw();
break;
caseVK_RIGHT:
Theta=Theta+IncAng;
Mydraw();
break;
caseVK_LEFT:
Theta=Theta-IncAng;
Mydraw();
break;
default:
break;
}
}
/////////////////////////////////////////////////////////////////////////////
voidCMyView:
:
OnTumianti()
{//透视投影赋初值
Rol=1600.0;
S=1;
Theta=60;
Phi=135;
DE=1000;
Mydraw();
CDC*pDC=GetDC();
pDC->TextOut(200,200,"按下键盘上的“上”、“下”、“左”、“右”键,可观看各方位图形");
ReleaseDC(pDC);
}
/////////////////////////////////////////////////////////////////////////////
voidCMyView:
:
OnYuanjin()
{
CClientDC*pdc=newCClientDC(this);
CPen*pen1=newCPen(PS_SOLID,1,RGB(0,0XFF,0));
CPen*pen2=newCPen(PS_SOLID,1,RGB(255,0,0));
CPen*OldPen=pdc->SelectObject(pen1);
CBrushbrush;
brush.CreateSolidBrush(RGB(0,0,0));
CBrush*oldbrush=(CBrush*)pdc->SelectObject(&brush);
intflag,k1,k2,r1,r2,n,d,m,p;
intxs1,xs2,xs3,xs4,ys1,ys2,ys3,ys4,i,j,lastp;
doublex,y,z,thx,th1,th3,yw,zw,xw,thy,th2;
doublePI,ed,od,eh,zzw,ppw;
doublexs[50][17],zs[50][17],ys[50][17],zc[50][17],x1,y1;
intzz[850],pp[850];
r1=100;r2=40;k1=20;k2=16;ed=1500;eh=0;od=0;
n=0;PI=3.14159;th3=1;thx=0.9;
//计算顶点坐标值
for(d=-1;d<=1;d+=2){
for(th1=0;th1<=2*PI+0.1;th1+=2*PI/k1){
n=n+1;m=0;
for(th2=0;th2<=2*PI+0.1;th2+=2*PI/k2){
m=m+1;
x=r1+r2*cos(th2);
y=r2*sin(th2);
z=0;
thy=th1;
zw=z;xw=x;
x=zw*cos(thy)-xw*sin(thy);
z=zw*sin(thy)+xw*cos(thy);
x=x+r1/2*d;
if(d==1)
{
yw=y;
zw=z;
y=yw*cos(PI/2)-zw*sin(PI/2);
z=yw*sin(PI/2)+zw*cos(PI/2);
}
thy=th3;
zw=z;xw=x;
x=zw*cos(thy)-xw*sin(thy);
z=zw*sin(thy)+xw*cos(thy);
yw=y;zw=z;
y=yw*cos(thx)-zw*sin(thx);
z=yw*sin(thx)+zw*cos(thx);
x=x*ed/(ed-od-z);
y=(y*ed-eh*(od+z))/(ed-od-z);
xs[n][m]=x;
ys[n][m]=y;
zs[n][m]=z;
}
flag=0;
//Nextth1
}
flag=0;
//Nextd
}
//计算center值
p=0;
for(n=1;n<=k1;n+=1){
for(m=1;m<=k2;m+=1){
zc[n][m]=int((zs[n][m]+zs[n+1][m+1])/2);
zz[p]=zc[n][m];
pp[p]=p;
p=p+1;
}
}
lastp=p-1;
//排序
for(i=2;i<=lastp;i+=1){
for(j=i-1;j>=0;j+=-1){
if(zz[j]>zz[j+1]){
zzw=zz[j];
zz[j]=zz[j+1];
zz[j+1]=zzw;
ppw=pp[j];
pp[j]=pp[j+1];
pp[j+1]=ppw;
}
}
}
//绘图
for(p=0;p<=lastp;p+=1){
n=int(pp[p]/k2)+1;
m=pp[p]%k2+1;
if(n!
=(k1+1)){
xs1=int(xs[n][m]);ys1=int(ys[n][m]);
xs2=int(xs[n+1][m]);ys2=int(ys[n+1][m]);
xs3=int(xs[n+1][m+1]);ys3=int(ys[n+1][m+1]);
xs4=int(xs[n][m+1]);ys4=int(ys[n][m+1]);
if(abs(ys1*(xs2-xs3)+ys2*(xs3-xs1)+ys3*(xs1-xs2))>80){
pdc->MoveTo(xs1+320,ys1+200);
pdc->SelectObject(pen1);
pdc->LineTo(xs2+320,ys2+200);
pdc->LineTo(xs3+320,ys3+200);
pdc->LineTo(xs4+320,ys4+200);
pdc->LineTo(xs1+320,ys1+200);
x=(xs[n][m]+xs[n+1][m+1])/2;
y=(ys[n][m]+ys[n+1][m+1])/2;
x1=int(x+320);
y1=int(y+200);
pdc->ExtFloodFill(x1,y1,RGB(0,255,0),0);
//endif
}
pd
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机图形学大作业 课程设计 实验报告 消隐算法 计算机 图形学 作业 实验 报告 算法
![提示](https://static.bdocx.com/images/bang_tan.gif)