1、计算机图形学大作业 课程设计 实验报告 消隐算法安徽建筑工业学院计算机图形学 大作业 大作业名称: 消隐算法 演示 院(系)名称: 专 业: 班 级: 姓 名: 学 号: 指 导 老 师: 2011 2012年度第 一 学期计算机图形学消隐算法1、设计目的:通过检测可见面,消除隐藏线和隐藏面,以在二维平面上显示具有真实感图形。消除隐藏线和隐藏面,是计算机图形学中比较因难但又是十分关键的一个问题。消隐算法是决定相对于空间给定位置的观察者,哪些线、表面或物体是可见的,哪些是不可见的。本章主要展示和计论一些最常用的隐藏线和隐藏面的消隐方法及技术。2、设计思想:投影变换失去了深度信息,往往导致图形的二
2、义性,要消除二义性,就必须在绘制时消除被遮挡的不可见的线或面,习惯上称作消除隐藏线和隐藏面,简称为消隐。经过消隐得到的投影图称为物体的真实图形。 确定算法类到目前为止,已经提出了很多有效的消隐算法,这些算法可以依据算法实现时所在的坐标系或空间进行分类,一般可分成两大类:对象空间算法和图像空间算法。本文采用的就是图像空间算法(image-space methods),这种方法是对投影平面或显示屏幕上的每一个像素位置逐点地检测其可见性。这种算法比较粗糙而且按图像空间算法得到的画面在放大后往往不能令人满意。但这种算法计算效率比较高,因为在光栅扫描过程中可以充分利用画面的连贯性等性质。 确定集体的实现
3、算法1. 消除隐藏线对造型的要求在线框显示模型中,要求造型系统中有面的信息,最好有体的信息。坐标变换将视点变换到Z轴的正无穷大处,视线方向变为Z轴的负方向。最基本的运算判断面对线的遮挡关系.反复地进行线线、线面之间的求交运算2. 面消隐面消隐算法的分类(图像空间的消隐算法,物体空间的消隐算法)提高消隐算法效率的常见方法(利用连贯性,将透视投影转换成平行投影,包围盒技术,背面剔除,空间分割技术,物体分层表示)本文是利用Z-Buffer算法的思想运用几何知识实现的,称为Z-Buffer算法的改进算法。3、设计过程: Z-Buffer算法的思想:先将Z缓冲器中个单元的初始值置为最小值。当要改变某个像
4、素的颜色值时,首先检查当前多边形的深度值是否大于该像素原来的深度值(保存在该像素所对应的Z缓冲器的单元中),如果大于,说明当前多边形更靠近观察点,用它的颜色替换像素原来的颜色;否则说明在当前像素处,当前多边形被前面所绘制的多边形遮挡了,是不可见的,像素的颜色值不改变。 改进法:通过记录投影与当前扫描线相交的多边形。1 求点的平行投影和透视投影坐标值2 用三维点坐标直接从当前点画线到某点3 三维坐标下直接将当前点移动到某点4 表面三个顶点调用求该表面的法矢5 求观察方向矢量与表面法矢的数量积6 画出立体上的平面并绘出消隐立体图4、设计总结: 选择不同的消隐算法消隐问题有不同的算法,有些算法要求速
5、度快,有些要求图形的真实度高。例如,快速消隐算法可用于实时模拟如飞行模拟等;具有高度真实感图形的消隐算法可用于计算机动画等领域,所生成的图形一般具有连续色调,并能产生阴影、透明、表面纹理及反射、折射等视觉效果。不过这类算法比较慢。产生一幅图可能需要几分钟甚至几小时。所以,在进行消隐算法的设计时,应在计算速度和图形细节之间进行权衡,任何一种算法都不能兼顾两者。 消隐算法的实现空间消隐算法可以在物体空间或图像空间中实现。 物体空间算法是在定义物体的坐标系中实现的,而图像空间算法是在对象显示的屏幕坐标系中实现的。 物体空间算法以尽可能高的精度完成几何计算,所以可以把图像放大许多倍而不致损害其准确性,
6、但是图像空间算法只能以与显示屏的分辨率相适应的精度来完成计算,所以其图像的放大效果较差。 这两类算法的性能特性也是不同的。物体空间算法所需的计算时间随场量中物体的个数而增加,而图像空间的计算时间则随图像中可见部分的复杂程度而增加。5、设计平台:Computer(Windows xp),VC+6、附件:void CMyView:Project(float X, float Y, float Z)/ 此函数求点的平行投影和透视投影坐标值 XObs = -X * Aux1 + Y * Aux3; YObs = -X * Aux5 - Y * Aux6 + Z * Aux4; / 求透视投影坐标值 Z
7、Obs = -X * Aux7 - Y * Aux8 - Z * Aux2 + Rol; XProj = DE * XObs / ZObs; YProj = DE * YObs / ZObs;/void CMyView:WLineTo(float X, float Y, float Z,CDC*pDC)/ 用三维点坐标直接从当前点画线到一点的函数 Project(X, Y, Z); / 将三维点作投影 XScreen = floor(0.5 + XProj * Scale +150); / 圆整 YScreen = floor(0.5 + 100 - YProj); / 圆整 pDC-Line
8、To(XScreen, YScreen); / 画线到一点/void CMyView:WMoveTo(float X, float Y, float Z,CDC*pDC)/ 三维坐标下直接将当前点移动到某点的函数 Project (X, Y, Z); / 将三维点作投影 XScreen = floor(0.5 + XProj * Scale + 150); / 圆整 YScreen = floor(0.5 + 100 - YProj); / 圆整 pDC-MoveTo(XScreen, YScreen); /移动到某点/void CMyView:ReadVertics()/ 此函数用来给数组S
9、t的元素赋顶点坐标值 St11 = 40; St12 = 154; St13 =-20; St21 = 40; St22 = 154; St23 = 0; St31 = 40; St32 =46; St33 = 0; St41 = 40; St42 =46; St43 =-20; St51 =-40; St52 =46; St53 =-20; St61 =-40; St62 = 154; St63 =-20; St71 =-40; St72 = 154; St73 = 0; St81 = 0; St82 = 134; St83 = 40; St91 = 0; St92 =66; St93 =
10、40; St101 =-40; St102 =46; St103 = 0;/void CMyView:ReadFaces()/ 此函数给数组Fc的元素赋表面有关的数据值 NF= 9; Fc10=4; Fc11=1; Fc12=2; Fc13=3; Fc14=4; Fc20=4; Fc21=1; Fc22=6; Fc23=7; Fc24=2; Fc30=3; Fc31=2; Fc32=7; Fc33=8; Fc40=4; Fc41=2; Fc42=8; Fc43=9; Fc44=3; Fc50=4; Fc51=1; Fc52=4; Fc53=5; Fc54=6; Fc60=4; Fc61=7;
11、Fc62=10; Fc63=9; Fc64=8; Fc70=3; Fc71=3; Fc72=9; Fc73=10; Fc80=4; Fc81=10; Fc82=5; Fc83=4; Fc84=3; Fc90=4; Fc91=5; Fc92=10; Fc93=7; Fc94=6;/void CMyView:VisionVector(int St1) /* 该函数用于求观察方向矢量 St1 is the first point of a face. */ v1=O1-StSt11; v2=O2-StSt12; v3=O3-StSt13;/void CMyView:NormalVector(int
12、St1, int St2, int St3)/ 此函数用表面三个顶点调用求该表面的法矢float P1, P2, P3, Q1, Q2, Q3; P1 = StSt21 - StSt11; / 求一个向量 P2 = StSt22 - StSt12; P3 = StSt23 - StSt13; Q1 = StSt31 - StSt11; / 求另一个向量 Q2 = StSt32 - StSt12; Q3 = StSt33 - StSt13; n1 = P2 * Q3 - Q2 * P3; /用向量积求法向量 n2 = P3 * Q1 - Q3 * P1; n3 = P1 * Q2 - Q1 *
13、P2;/float CMyView:ScaleProduct(float v1, float v2, float v3, float n1, float n2, float n3)/ 此函数用于求观察方向矢量与表面法矢的数量积float SProduct; SProduct = v1 * n1 + v2 * n2 + v3 * n3; return(SProduct);/void CMyView:DrawFace(CDC*pDC)/ 画出立体上的平面int S, NS, No;float X, Y, Z, X0, Y0, Z0; NS = FcF0; for ( S = 1; SSelectO
14、bject(&pen1); for ( F = 1; F 0 ) / 判断数量积正否 pDC-SelectObject(&pen1); DrawFace(pDC); / 数量积大于零,表面可见,画出此表面 else; pDC-SelectObject(pOldPen); ReleaseDC(pDC);/void CMyView:VisionPoint()/ 此函数用于给出视点位置/ 投影时初始值即正弦值和余弦值及其乘积的计算、赋值 float Th, Ph; Th = 3.1415926 * Theta / 180; Ph = 3.1415926 * Phi / 180; Aux1 = sin
15、(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;/void CMyView:Mydraw() RedrawWindow(); ReadVertics(); ReadFaces(); / 绘出透视投影下的凸多面体图形 VisionPoint(); / 给出视点位置
16、DrawObject(); / 画出立体的图形/void CMyView:OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) /此函数用来利用上下左右键移动视点角度位置 switch(nChar) case VK_UP: Phi=Phi-IncAng; Mydraw(); break; case VK_DOWN: Phi=Phi+IncAng; Mydraw(); break; case VK_RIGHT: Theta=Theta+IncAng; Mydraw(); break; case VK_LEFT: Theta=Theta-IncAng;
17、Mydraw(); break; default: break; /void CMyView:OnTumianti() /透视投影赋初值 Rol = 1600.0; S=1; Theta = 60; Phi = 135; DE = 1000; Mydraw(); CDC*pDC=GetDC(); pDC-TextOut(200,200,按下键盘上的“上”、“下”、“左”、“右”键,可观看各方位图形); ReleaseDC(pDC);/void CMyView:OnYuanjin() CClientDC *pdc=new CClientDC(this); CPen *pen1=new CPen(
18、PS_SOLID,1,RGB(0,0XFF,0); CPen *pen2=new CPen(PS_SOLID,1,RGB(255,0,0); CPen *OldPen=pdc-SelectObject(pen1); CBrush brush; brush.CreateSolidBrush(RGB(0,0,0); CBrush *oldbrush=(CBrush*)pdc-SelectObject(&brush); int flag,k1,k2,r1,r2,n,d,m,p; int xs1,xs2,xs3,xs4,ys1,ys2,ys3,ys4,i,j,lastp; double x,y,z,t
19、hx,th1,th3,yw,zw,xw,thy,th2; double PI,ed,od,eh,zzw,ppw; double xs5017,zs5017,ys5017,zc5017,x1,y1; int zz850,pp850; 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
20、/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
21、; 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); xsnm=x; ysnm=y; zsnm=z; flag=0; /Next th1 flag=0; /Next d /计算center值p=0; for(n=1;n=k1;n+=1) for(m=1;m=k2;m+=1) zcnm=int(zsnm+zsn+1m+1)/2); zzp=zcnm; ppp=p; p=p+1; lastp=p-1; /排序 for(i=2;i=0;j+=-1)
22、if(zzjzzj+1) zzw=zzj; zzj=zzj+1; zzj+1=zzw; ppw=ppj; ppj=ppj+1; ppj+1=ppw; /绘图 for(p=0;p80) 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=(xsnm+xsn+1m+1)/2; y=(ysnm+ysn+1m+1)/2; x1=int(x+320); y1=int(y+200); pdc-ExtFloodFill(x1,y1,RGB(0,255,0),0); /endif pd
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1