计算机图形学实验报告(精选6篇)
1.计算机图形学实验报告 篇一
计算机图形学实验报告
0900213 38 8 郭佩佩
实验一
建立计图实验环境 1. 实验目的 为了体现面向对象的程序设计思想,本实验采用基于 Visual C 十十集成环境的 MFC 编程方法,从开发 windows 应用程序的角度,来建立一个菜单交互式绘图基本环境,为后续的实验打基础。
2. 实验内容 1)
建立菜单交互式绘图基本环境的工程文件 Vcad,运行后如图:
2)在绘图菜单的下拉子菜单下有如下菜单项:
直线
----用弹性线方法输入直线的起止点后,调用 bresenham 算法替换原来
的 moveto/lineto 算法画直线
圆/圆弧
----在该菜单选择后,可分别画圆或圆弧。
直线段裁剪----输入矩形域左上角及右下角后,产生裁剪区域;然后可输入若干条直线段,矩形域作为主裁剪域对其裁剪之。
面区填充
----输入多边形的若干顶点后,调用面区填充算法对多边形域的内部填充
之。
贝塞尔曲线----输入四顶点后,调用三次贝塞尔曲线生成算法生成贝塞尔曲线。
实验二
园和园弧的绘制算法
1.实验目的 通过园和椭圆弧生成算法的上机调试,掌握:
1)
VC++图形函数的使用方法; 2)
圆和椭圆弧的生成原理。
2.实验内容 1)以函数形式编写圆的生成算法,然后在 VCAD 绘图小系统中的绘图----圆子菜单下找到合适的程序修改点,将本实验要求你编写的画圆算法插入工程文件中,通过调试来验证你编写的画圆算法的正确性。
2)
以函数形式编写角度 DDA 椭圆弧生成算法,然后在 VCAD 绘图小系统中的绘图----圆弧子菜单下找到合适的程序修改点,将本实验要求你编写的画圆弧算法插入工程文件中,通过调试来验证你编写的画圆弧算法的正确性。
Arc(int xc,int yc,doubli r,double ts,double te){
double rad,ts1,tel,deg,dte,ta,ct,st;
int x,y,n,I;
rad=0.0174533;
tsl=ts*rad;
tel=te*rad;
if(r<5.08)
deg=0.015;
else
if(r<7.62)
deg=0.06;
else
if(r<25.4)
deg=0.075;
else
deg=0.15;
dte=deg*25.4/r;
if(tel tel+=6.28319; n=(int)((tel-tsl)/dte+0.5);if(n==0) n=(int)(6.28319/dte+0.5); ta=tsl; x=xc+r*cos(tsl); y=yc+r*sin(tsl); moveto(x,y); for(i=1;i<=n;i+++) { ta+=dte;ct=cos(ta);st=sin(ta);x=xc+r*ct;y=yc+r*st;lineto(x,y);} x=xc+r*cos(tel); y=yc+r*sin(tel); lineto(x,y); return(0);} 实验三 直线的裁剪(编码裁剪算法) 1. 实验目的 通过编码裁剪算法的设计与调试,了解二维线段的裁剪过程,提高程序设计能力与上机调试能力,达到理论与实践有机结合之目的。注:此实验已有可运行的中点裁剪算法作为参考实例,做实验时,可将中点裁剪算法替换为你编写的编码裁剪算法。 2. 实验内容 1) 以函数形式编写编码裁剪算法及相关子算法; Var xl,xr,yb,yt:real;…… procedure clip(x1,y1,x2,y2:real);label:return;type edge=(L,R,B,T); outcode=set of edge;Var c,c1,c2:outcode;x,y:real;Procedure code(x,y:real;Var c:outcode); Begin c:=[ ]; If x Else if x>xr then c:=[R]; If y Else if y>yt then c:=c+[T]; End {end of code} Begin {main} Code(x1,y1,c1);code(x2,y2,c2);While(c1<>[])or(c2<>[])do Begin if c1*c2<>[] then return;{显然不可见} c:=c1;if c=[] then c:=c2; If L in c then begin x:=xl;y:=…end;{对左边界求交} If R in c then begin x:=xr;y:=…end;{对右边界求交} If B in c then begin x:=…;y:=yb end;{对底边界求交} If T in c then begin x:=…;y:=yt end;{对顶边界求交} If c=c1 then begin x1:=x;y1:=y; code(x,y,c1)end Else begig x2:=x,y2:=y; code(x,y,c2)end End;{End of while} Line(x1,y1,x2,y2); Return: end;{end of clip} 2) 交互产生矩形裁剪框,并输入不同斜率的直线段的始、终点,先画出此直线段,然后调用裁剪算法,画出裁剪后保留的可见线段部分。 3) 在 VCAD 绘图小系统中的绘图----直线裁剪子菜单下找到合适的修改点,将本实验要求你编写的编码裁剪算法替换掉工程文件中的中点裁剪算法,通过调试来验证你编写的编码裁剪算法的正确性。 实验四 面区填充(Y-X 算法) 1. 实验目的 通过 Y-X 面区填充算法的调试,掌握: 1) 多边形面区填充算法的数据组织; 2) 利用相关性提高算法效率; 3) 奇异点的处理方法; 4) 提高程序设计能力。 2. 实验内容 1) 以函数形式编写 Y-X 面区填充算法; 2) 在 VCAD 绘图小系统中的绘图----面区填充子菜单下找到合适的修改点,将本实验要求你编写的面区填充算法插入工程文件中,通过调试来验证你编写的面区填充算法的正确性。操作时,用鼠标交互给出多边形的若干顶点,画出此多边形,然后调用你编写的 Y-X 面区填充算法填充,以自选的颜色填充多边形。 实验五 贝塞尔曲线生成算法的设计与调试 一、实验目的 在掌握曲线、曲面数学理论的基础上,通过调试,绘制 Bezier 曲线。加深同学 对数学理论的理解。通过二条 Bezier 曲线的拼接设计,掌握自由曲线的拟合方法。 二、内容和要求 1、由三次 Bezier 曲线的公式:P(t)=∑P i B i,3(t) 出发,编写生成 Bezier i=0 曲线的程序,要求如下: a) 用鼠标输入特征多边形的四点。然后调用 Bezier 曲线生成算法绘出曲线。 b) 重复上步 3—4 遍,验证你编写的算法的正确性。 typedef cptype float[4][4];float cc(int n,int i)//计算 n!/(i!(n-i)!) {int j; float a; a=1; for(j=i+1;j<=n;j++)a*=j; for(j=2;j<=n-i;j++)a/=j; return a; } float b_lend(Int i,int n,float t2)//计算 B i,n(t) {float v; v=cc(n,i);for(j= 1;j<=i;j++)v*=t2; for(j=1;j<=n-i;j++)v*=(1-t2); return v; } void bezier(float x0,float y0,float z0,float t0,int n,cptype cp2)//给定 t0,计算 f(t0){int i; float b1,g; for(i=0;i<=n;i++){b1=b_lend(i,n,t0); x0=x0+cp2[i,1]*b1;y0=y0+cp2[i,2]*b1;z0=z0+cp2[i,3]*b1;}} void draw_curv(int k,cptype cp1)//将 t 分成 k 等份,循环迭代,绘出曲线。 {int i,j,x1,y1,z1; float x,y,z,delt; delt=1.0/k; t=0; for(i=1;i<=k;i++) {x=y=z=0; bezier(x,y,z,t,3,cp1); if(t==0)moveto(x,y); else lineto(x,y); t+=delt;}} 2、将特征多边形改为五个控制点,修改程序后绘出四次曲线。 3、实现二条三次 Bezier 的拼接,并使连接点处保持一阶连续。 实验小结: 实验的过程是辛苦的,特别是处理大量的数据,大量的临时变量,很容易出错,需要极大的耐心。一些计算时,例如DDA 算法画圆时,需要强制类型转换一些数据,因为遗漏导致程序出了许多奇怪的错误,调试很久才发现。另外,贝塞尔曲线的算法编写中,一些数学函数的调用也很复杂,因为不常用,所以经常翻阅 API 文档。 最困难的是因为对该图形系统的不熟悉,导致处理鼠标操作时遇到一些难题,仔细比对才得以解决。 通过本次实验,对整个图形系统有了比较透彻的了解,同时对一些数学函数的使用再次加深了印象,更重要的是掌握了许多实用的计算机图形学的算法,对 MFC 的使用有了很大提升。 这次实验中积累的经验在今后的软件开发中将使我受益匪浅。 2005 年 1 月 3 日 1 计算机图形学教学中的问题及其原因分析 计算机图形学应该来说具有非常广泛的使用范围, 很多学生对于这门课的态度是刚接触的时候挺喜欢, 但是, 随着学习过程的慢慢开展, 他们的主动性和积极性就慢慢被消磨掉了, 他们开始不注重学习的创新能力, 而仅仅为了得到相应的学分。这种现状的产生主要是由于以下几个方面的因素: 1) 学习难度较大。由于计算机图形学涉及的知识面非常广, 其中不仅有计算机知识, 还有数学等其他学科的知识, 因此, 它的知识基础要求较高, 学生学习起来难度较大也是情理之中的事情。事实上, 计算机图形学是一门新兴学科, 它是建立在图论、现代数学和计算机科学基础之上的, 学科交叉繁杂, 其理论性很强, 同时实践性又不弱, 这就让学生体会到了该门课程的综合性特征和难易掌握的感觉, 从而让他们在巨大的学习难度面前望而却步; 2) 教学理念较为滞后。当前的计算机图形学教学观念仍然沿用的是传统的教学观念, 重视教师的单方面的知识传授, 片面强调学生对于相关知识点的掌握程度。这样的教学观念往往使得教学在备课的时候, 片面追求教学大纲的要求, 非常详细讲解每一堂课的知识点。这样的背景之下, 教师容易把计算机图形学课堂变成满堂灌, 学生就是一种被动的学习状态, 师生之间的互动性不高, 学生的学习积极性和主动性自然也就大打折扣了。此外, 传统的教学观念中不太重视实验教学环节, 更不会重视学生实践能力的培养, 大大阻碍了学生的创新精神培养与创新能力的提高; 3) 实验教学环节不够科学与系统。当前, 计算机图形学教学过程中的实验环节, 很多高校一直采用C或VC++来实现编程, 同时, 进行实验的工具与内容又较为陈旧, 考核方式也颇为单调, 学时又不太多, 使得学生对于计算机图形学的学习兴趣大大降低, 而且学习起来的真实难度又是较大的, 尤其是绘制模型的实现, 使得学生的实验能力有待加强。 2 Open GL图形系统及其在图形学上的应用 所谓Open GL图形系统, 指的就是一个丰富的三维图形函数库, 是图形系统中的一个软件接口, 允许程序开发者创建一个交互性的程序, 从而能够产生三维移动的物体的彩色图像。它除了具有基本的Open GL函数以外, 还能够支持Open GL实用库、Open GL辅助库、Windows专用库函数、Win32 API函数等其他四类函数。它还可以有双缓存的功能, 主要应用于制作动画。我们可以使用Open GL图形系统来对计算机图形技术进行相关的控制, 从而产生较为逼真的图形或者虚拟出实际生活中没有的图像。一般来说, Open GL图形系统的应用非常广泛, 具体应用到计算机图形学中的话, 就是说我们可以利用Open GL函数来顺利实现图形算法的演示。这种方法可以提高许多图形函数, 让它们能够通过单独调用或者组合某些函数来实现基本的图像操作, 还可以对光线进行调整。目前, 随着计算机技术的不断发展, 现在的Open GL图形库中增加了不少新组件, 已经可以产生形象化的三维效果。当前常用的图形设计方法有:图形生成算法、几何变换、投影变换等。具体应用步骤如下:建立基本模型、投影及视口变换、光照、材质、雾等的设置、显示三维图形。其中, 建立基本模型就是指利用技术手段来提取真实物体的表面离散点, 然后输入到计算机中去, 从而形成三角网络模型。就投影及视口变换来说, Open GL函数主要提供了正射投影和透视投影两种投影方式。然后, 对模型进行光照设置, 这里的光照设置包含了环境光、漫反射光和镜面反射光等三种, 对于材质的设置与光源类似, 让其能够更加接近于真实物体。至于雾化, 主要是使得物体能够更加自然逼真, 具有一定的立体感。最后, 完成以上三个步骤就显示三维图形。此外, Open GL图形系统函数库还可以进行纹理设置、特殊光照处理以及实现动画效果等其他方面的强大功能。 3 基于Open GL实验平台进行计算机图形学教学改革 一般来说, 计算机图形学具有非常广泛的应用领域, 比如说信息显示、设计、仿真与动画以及用户界面等方面。如果我们应用Open GL图形系统实验平台, 将对传统的教学应用思想产生一定的冲击和影响。从传统的教学思想来看, 我们往往习惯于选择Powerpoint中的课件制作组件来制作课件, 虽然它能够解决基本的图形问题, 但是, 一旦碰到较为抽象和复杂的图形学理论, 就难以应对。因此, 笔者认为, 我们应该采用一种新型的图形学理论来指导我们的课件制作, 以增加图形的逼真程度和提高图形学课件的制作质量。在此, 笔者提出了我们可以基于Open GL图形系统实验平台来将不同的知识点进行课件制作, 努力培养学生上机进行实践的兴趣和主动性, 让学生提高互动参与性, 从而提高他们的学习效果。但是, 当前我国高校计算机图形学教学现状不容乐观, 还存在着不少急需解决的问题。因此, 我们应该尽快采用Open GL实验平台来加强计算机图形学教学改革。具体如下: 1) 高校应该首先认清楚Open GL图形系统的真实内涵, 充分利用其优秀的图形处理资源和演示效果来大大激发出学生的学习心理, 让他们主动参与到实践中来, 对抽象的内容进行具体化的解读。这就需要学校改变传统的教学观念, 因为传统的教学观念仍然是以教师教授知识为主, 学生处于被动消极的地位, 他们的学习积极性和主动性被严重的压抑了, 而这与理论性实践性兼具的计算机图形学教学来说, 是相背离的。它的基本内容就是要学习传统的经典计算方法, 然后再学会分析并改进计算方法, 最后解决相关问题。因此, 传统的教学观念显然是不能够适应这种教学要求的。因此, 我们应该彻底改变原来的教学观念, 建立一种以培养学生能力为目标的新型教学模式, 让学生积极参与到学习过程中, 做学习的主人, 并逐步培养并提高自身的分析与解决问题的能力; 2) 高校要尽量调整相关的实验工具, 重新设置实验项目。我们知道, Open GL图形系统是一个非常专业的图形程序接口, 它具有非常强大的图形数据库, 提供了基本库、实用库和辅助库三个方面的函数库, 可以开发二维和三维图形程序所需要的多个方面。我们如果在计算机图形学的教学中很好的应用Open GL图形系统, 就可以把它作为基础开发的应用程序, 独立于窗口系统和操作系统来实现不同平台之间的移植工作。因此, 计算机图形学教学中适当的借助于Open GL实验平台, 可以与图形算法进行合理的结合。这种教学方法可以满足学生的学习需求, 还可以培养他们的实际应用能力, 并设置新的实验项目, 让学生很好的掌握基本的算法, 培养学生的科研和分析实践能力; 3) 考核方法要改进。当前, 计算机图形学教学的考核方法过于单一, 大大消磨了学生的学习积极性和主动性。那么, 我们就要适当的改革以前的那种考核办法, 而应该根据学生的实际情况, 采用多因素和异权重的综合考核办法来增加学生成绩评定体系的科学性和合理性。因为正确合理的评价体系是保证教学质量的重要手段之一, 它有利于调动学生的积极性, 提高他们的创新思维, 还可以让教师引领学生及时发现问题并解决问题。具体来说, 学校可以采用一体化的教学过程评价方法, 综合学生在整个学习过程中的学习态度、操作情况、参与实践教学的主动性、创造性、正确性等来给予学生综合性的成绩评定, 而不是简单的依赖于理论考试和实验报告来决定他们的最终学习成绩。这样就可以培养出既有专业理论知识, 又有一定实际操作能力和创新能力的新世纪复合型人才。 4 结束语 总之, 作为一门新兴的学科, 计算机图形学教学在信息化时代显得日益重要。我们要针对当前计算机图形学教学现状和问题, 有意识的改革传统的教学观念, 建立基于Open GL实验平台的计算机图形学教学模式, 狠抓学生基本功练习, 合理安排一体化学习任务, 把握理论知识和技能教学的穿插时机, 认真设计学习任务, 激发学生的学习兴趣, 提高学生的学习积极性, 并采用综合性的评价体系来进行及时总结评价, 激发积极向上的学习热情等, 使得兼具理论性和实践性的计算机专业课程, 即计算机图形学课程的教学质量进一步得到提高, 从而培养出具有综合能力的计算机人才。 摘要:在当前这个世界图形时代, 人们的认知方式已经进入了视觉形象方式。在这样的数字化时代背景下, 计算机图形学的研究越来越显现出重要的地位和作用。因此, 该文将结合当前计算机图形学教学中的存在的一些问题, 提出了我们应该基于OpenGL实验平台, 尽快改革计算机图形学的教学模式, 让OpenGL很好的在计算机图形学教学中应用起来, 培养学生发现问题、解决问题的能力以及创新能力, 运用综合性的考核办法来切实提高当前计算机图形学教学质量。 关键词:OpenGL实验平台,计算机图形学,教学改革,教学质量 参考文献 [1]Francis S Hill.计算机图形学 (OpenGL版[M].3版.胡事民, 译.北京:清华大学出版社, 2010. [2]柳海兰.浅谈计算机图形学的发展及应用[J].电脑知识与技术, 2010 (3) :9551-9552. 摘 要: 由于计算机图形学是一门交叉学科,对老师和学生的要求都比较高,但是这门课用途广,应用也广,对学生的益处大,所以不少学校开设这门课。作者结合教学经验总结了一些促进课堂教学改革的方法,学生课堂反应效果良好。 关键词: 计算机图形学 教学改革 案例教学 1.引言 经过几十年的发展,计算机图形学已经成为集多种学科于一体的教全面的学科。计算机图形学的主要研究内容就是怎么在计算机中表示图形、利用计算机进行图形的计算、处理和显示的相关原理与算法。 2.课程教学的现状与问题 本课程讲授计算机图形学的有关理论、方法及编程技术,内容包括二维图形的生成及变换,样条曲线,三维图形几何造型及真实感图形生成,二维及三维图形编程。通过本课程的学习使学生掌握各种主要的图形生成及处理的原理和算法,掌握基本的图形编程技术,为今后从事相关的软硬件开发工作提供基础,并培养学生在算法研究方面的基本素养,提高学生的程序设计能力。 计算机图形学这门课程是很难理解的,不仅需要相关的数学知识,还需要有算法的思路,要学过计算机的编程语言,是一门交叉课程。这门课对老师的要求比较高,对学生的能力要求比较高。这门课是老师难上得好,学生不容易听得懂。所以本课程总学时48课时,其中安排实验12课时,主要是在C++6.0中安装OpenGL,在此环境中进行代码验证一些计算机图形学的算法。一方面学习了C++代码在实践应用中代码的编写,另一方面进一步对计算机图形学的相关算法和理论进行了验证和理解。 3.教学方法改革 (1)基础内容重点反复讲:对实质引入该门课程的基础内容重点逐步反复讲,在数学上直线是点的集合.在几何学中直线被定义为两个点之间的最短距离。也就是说一条直线是指所有在它上面的点的集合,直线是一维的,即它们具有长度但没有维数。但是图形学中的直线的概念,其一条线段就是由一些连续可见的像素所组成的。一再强调是像素,并且讲像素的概念。这个直线的概念和学生以前在数学上学习的概念不同,不讲清楚直线和像素的关系,对于该课程的其他内容学生根本就没法理解。 (2)提高学生学习该门课程的兴趣:计算机图形学虽然比较难,课程难上,但是只要能讲明白,学生听懂了,就不容易忘记。但是由于比较枯燥,怎么引发学生学习和听课的兴趣则是一个关键。加强提问,讲一点新内容,提问一次,让学生复述出来。学生基础打牢了,逐渐发现这门课有意思了。 (3)大量举实际案例讲解:如增量算法中,对于该算法怎么算出来的,就举了个实例,如怎么划直线段P0(0,0)到P1(5,2),一讲实例,学生对于刚才讲的增量算法的算法过程就明白了。在讲每个算法后,都举一个到几个实例,慢慢分析,学生就听明白了,并且越来越感兴趣。 (4)加入板书:由于大量举实例,为了使学生明白每一步算法是怎么来的,要用板书讲解实例。只有经过这样一步步的计算,学生的思路才能跟上老师的讲解速度,如果全部都用PPT讲述,速度太快,学生就可能对案例分析的速度跟不上。 (5)PPT加入动画:由于计算机图形学课程比较枯燥,每张PPT都有动画,能够吸引学生的注意,符合当代大学生喜欢高科技喜欢新生事物的心理。 (6)加强课堂中与学生的交流:学生对老师要求比较高,师生在课程教学中要不断交流。这里主要有眼神的交流,在上这门课时不断留心学生对授课的反应,如果发现不明白,就在深化后讲一遍,同时可以让学习成绩比较好的同学讲讲理解,这样全班学生的注意力都全部集中在课堂上了。 (7)讲课时注意运用语言的魅力。讲课要抑扬顿挫,注意语气的运用,有舒有缓,有急有慢,充分利用声音和语言的魅力,将学生吸引到课堂上,这样一堂课不仅效率高,学生还记得很牢。 (8)讲解代码加深学生对算法的认识。大四学生已学习了两种以上的编程语言,通过讲解该课程的代码,不仅复习了编程语言,而且加深了对算法内容的认识,从不同角度分析了算法,学生如果以后工作中用到该算法,不仅理解并记得还可以写出代码,符合计算机专业培养的目标。 (9)改写代码训练学生的实践能力。通过书上给的现成代码进行演练后,在学生已经掌握的基础上,要求学生改写该算法或者理论代码,一般都不仅书上这一种代码可实现。通过一步步引领学生改写代码,学生的代码实践能力得到了迅速提高。 (10)复习相关的数学知识。在授课过程中发现学生在大学数学基础课中的数学知识理解得不透所以记得不牢靠,有必要对计算机图形学要运用较多的矩阵知识进行提高性的复习。如对矢量和矩阵的知识进行复习,特别是对矩阵乘法进行重点复习。 4.结语 通过对这门课程的认真研究,积极准备想尽办法,充分利用一切教学手段加上大量举例,使这门课上得生动易理解,学生爱上课,上课积极听课,并且能够积极回答课堂提问,补充回答问题的同学也很多,课堂气氛很好,学习气氛浓烈,达到了预期的教学目的。 参考文献: [1]王振武.计算机图形学基础[M]北京:清华大学出版社,2011. 课程名称 : 计算机图形学 实验名称 : 图形绘制与变换 学 院 : 电子信息工程学院 专 业 : 计算机科学与技术 班 级 : 11计科本 01班 学 号 : 111102020103 姓 名 : 张慧 指导教师 : 王征风 二零一四年 目录 一、引言----------------3 二、设计需求---------3 2.1 设计目标--3 2.2 设计环境--3 2.2.1 VC++6.0------------------------3 2.2.2 MFC------------------------------4 2.3 设计题目及要求----------------------4 2.4 总体流程图----------------------------4 三、课程设计原理---5 3.1 实现的算法------------------------------5 3.1.2 Bresenham算法画直线------5 3.1.3 中心点算法画圆和椭圆------5 3.2 图形变换的基本原理------------------7 3.2.1平移变换------------------------7 3.2.2 旋转变换----------------------8 3.2.3 比例变换----------------------8 四、总体设计与功能实现-------------------------8 4.1 主要界面设计---------------------------8 4.2 设置颜色界面---------------------------8 4.2.1 界面设置代码------------------8 4.2.2 运行结果------------------------9 4.3 二维线画图元实现---------------------9 4.4 画多边形功能的实现--------------13 4.5 画Bezier曲线功能的实现-------14 4.6 二维图形变换的实现--------------16 4.7 三维图形的变换--------------------17 五、实验心得体会 一、引言 计算机图形学(Computer Graphics,简称CG)是一种使用数学算法将二维或三维图形转化为计算机显示器的栅格形式的科学。简单地说,计算机图形学的主要研究内容就是研究如何在计算机中表示图形、以及利用计算机进行图形的计算、处理和显示的相关原理与算法。是计算机科学的一个分支领域,主要关注数字合成与操作视觉的图形内容。计算机图形学研究的是应用计算机产生图像的所有工作,不管图像是静态的还是动态的,可交互的还是固定的,等等。图形API是允许程序员开发包含交互式计算机图形操作的应用而不需要关注图形操作细节或任务系统细节的工具集。计算机图形学有着广泛的应用领域,包括物理、航天、电影、电视、游戏、艺术、广告、通信、天气预报等几乎所有领域都用到了计算机图形学的知识,这些领域通过计算机图形学将几何模型生成图像,将问题可视化从而为各领域更好的服务。 计算机图形学利用计算机产生让人赏心悦目的视觉效果,必须建立描述图形的几何模型还有光照模型,再加上视角、颜色、纹理等属性,再经过模型变换、视图变换、投影操作等,这些步骤从而实现一个完整的OpenGL程序效果。OpenGL是一个开放的三维图形软件包,它独立于窗口系统和操作系统,以它为基础开发的应用程序可以十分方便地在各种平台间移植。计算机图形学通过应用OpenGL的功能,使得生成的图形效果具有高度真实感。学习计算机图形学的重点是掌握OpenGL在图形学程序中的使用方法。事实上,图形学也把可以表示几何场景的曲线曲面造型技术和实体造型技术作为其主要的研究内容。同时,真实感图形计算的结果是以数字图像的方式提供的,计算机图形学也就和图像处理有着密切的关系。 通过21世纪是信息的时代,在日新月异的科技更新中相信计算机会发挥越来越重要的作用,计算机图形学也会在更多的领域所应用,虽然我国在这方面还比较薄弱,但相信会有越来越好的时候的。 二、设计需求 2.1 设计目标 以图形学算法为目标,深入研究。继而策划、设计并实现一个能够表现计算机图形学算法原理的或完整过程的演示系统,并能从某些方面作出评价和改进意见。通过完成一个完整程序,经历策划、设计、开发、测试、总结和验收各阶段,达到:巩固和实践计算机图形学课程中的理论和算法;学习表现计算机图形学算法的技巧;培养认真学习、积极探索的精神。 2.2 设计环境 2.2.1 VC++6.0 VC++6.0是 Microsoft 公司推出的一个基于 Windows 系统平台、可视化的 集成开发环境,它的源程序按 C++语言的要求编写,并加入了微软提供的功能 强大的 MFC(Microsoft Foundation Class)类库。MFC 中封装了大部分 Windows API 函数和 Windows 控件,它包含的功能涉及到整个 Windows 操作系统。MFC 不仅给用户提供了 Windows 图形环境下应用程序的框架,而且还提供了创建应 用程序的组件,这样,开发人员不必从头设计创建和管理一个标准 Windows 应 用程序所需的程序,而是从一个比较高的起点编程,故节省了大量的时间。另 外,它提供了大量的代码,指导用户编程时实现某些技术和功能。因此,使用VC++提供的 高度可视化的应用程序开发工具和 MFC 类库,可使应用程序开发变 得简单。2.2.2 MFC MFC(Microsoft Foundation Classes),是 一 个 微 软 公 司 提 供 的 类 库(class libraries)以 C++类的形式封装了 Windows 的 API,它包含了窗口等许多类的定义。各种类的集合构成了一个应运程序的框架结构,以减少应用程序开发人员的工作 量。其中包含的类包含大量 Windows 句柄封装类和很多 Windows 的内建控件和组 件的封装类。MFC 6.0 版本封装了大约 200 个类,其中的一些可以被用户直接使用。例如CWnd 类封装了窗口的功能,包括打印文本、绘制图形及跟踪鼠标指针的移动等;CsplitterWnd 类是从 CWnd 类派生出来的,继承了基类或称父类 CWnd 类的所 有特 性,但增加了自己的功能,实现拆分窗口,使窗口至少可被拆分成两个窗口,用户 可以移动两个窗口之间的边框来改变窗口的大小;CtoolBar 类可以定义工具栏等。MFC 命名的惯例是类的名字通常是由“C”打头;成员变量使用前缀“m_”,接着使用一个字母来指明数据类型,然后是变量的名称;所有的单词用大写字母开头。 2.3 设计题目及要求 (1)题目:实现多边形和曲线的绘制和变换 (2)要求:学会使用VC++编写实现图形的绘制变换,需包括直线、曲线、多边形的绘制和变换,及三维立体图形的相应变换.2.4 总体流程图 三、课程设计原理 3.1 实现的算法 3.1.1 DDA算法画直线 DDA是数字微分分析式(Digital Differential Analyzer)的缩写。 已知直线两端点(x1,y1)、(x2,y2)则斜率m为:m =(y2-y1)/(x2-x1)= Dx/Dy;直线中的每一点坐标都可以由前一点坐标变化一个增量(Dx, Dy)而得到,即表示为递归式: xi+1=xi+Dx yi+1=yi+Dy。 递归式的初值为直线的起点(x1, y1),这样,就可以用加法来生成一条直线。具体算法是: 该算法适合所有象限,其中用了用了两个函数如:Integer(-8.5)=-9;Integer(8.5)=8;Sign(i),根据i的正负,分别得到-1,0,+1; 相应代码: //DDA DrawLine {if(abs(x2-x1)> abs(y2-y1)) length = abs(x2-x1); else length = abs(y2-y1); Dx =(x2-x1)/length; Dy =(y2-y1)/length; x = x1+0.5*Sign(Dx); y = x2 + 0.5*Sign(Dy); i = 1; while(i <= lenght) { setpixel(Integer(x),Integer(y),color); x= x + Dx; y= y + Dy; i+=1;} } 3.1.2 Bresenham算法画直线 思路如下: // 假设该线段位于第一象限内且斜率大于0小于1,设起点为(x1,y1),终点为(x2,y2).// 根据对称性,可推导至全象限内的线段.1.画起点(x1,y1).2.准备画下个点。x坐标增1,判断如果达到终点,则完成。否则,由图中可知,下个要画的点要么为当前点的右邻接点,要么是当前点的右上邻接点.如果线段ax+by+c=0与x=x1+1的交点的y坐标大于M点的y坐标的话,下个点为U(x1+1,y1+1),否则,下个点为B(x1+1,y1),3.画点(U或者B).4.跳回第2步.5.结束.3.1.3中心点算法画圆和椭圆 (1)中心点算法画圆 在一个方向上取单位间隔,在另一个方向的取值由两种可能取值的中点离圆的远近而定。实际处理中,用决策变量的符号来确定象素点的选择,因此算法效率较高。生成圆弧的中点算 法和上面讲到的生成直线段的中点算法类似。 考虑第一象限内x[0,R/2]的八分之一圆弧段。经过计算,得出判别式的递推公式为: di1di2xi3di2(xiyi)5d0d0 (xi, M SE yi,r)E 这两个递推公式的初值条件为: (x0,y0,r)(0,R)d05/4R 编写成员函数如下: void CMy2_9View::MidPointEllipse(CDC *pDC, double a, double b, int color){ double x,y,d,xP,yP,squarea,squareb; squarea=a*a; squareb=b*b; xP=(int)(0.5+(double)squarea/sqrt((double)(squarea+squareb))); yP=(int)(0.5+(double)squareb/sqrt((double)(squarea+squareb))); x=0; y=b; d=4*(squareb-squarea*b)+squarea; pDC->SetPixel(x,y,color); while(x<=xP) {if(d<=0)d+=4*squareb*(2*x+3); else {d+=4*squareb*(2*x+3)-8*squarea*(y-1); y--;} x++; pDC->SetPixel(x,y,color);} x=a; y=0; d=4*(squarea-a*squareb)+squareb; pDC->SetPixel(x,y,color); while(y { if(d<=0)d+=4*squarea*(2*y+3); else {d+=4*squarea*(2*y+3)-8*squareb*(x-1); x--;} y++; pDC->SetPixel(x,y,color);}} 编写OnDraw函数如下: void CMy2_9View::OnDraw(CDC* pDC){CMy2_9Doc* pDoc = GetDocument();ASSERT_VALID(pDoc);MidPointEllipse(pDC,500,300,RGB(0,0,0));}(2)中心点算法画椭圆 我们先考虑圆心在原点的椭圆的生成,对于中心不是原点的椭圆,可以通过坐标的平移变换获得相应位置的椭圆。中心在原点。焦点在坐标轴上的标准椭圆具有X轴对称、Y轴对称和原点对称特性,已知椭圆上第一象限的P点坐标是(x, y),则椭圆在另外三个象限的对称点分别是(x,-y)、(-x, y)和(-x,-y)。因此,只要画出第一象限的四分之一椭圆,就可以利用这三个对称性得到整个椭圆。 相应代码: void MP_Ellipse(int xc , int yc , int a, int b){ double sqa = a * a;double sqb = b * b;double d = sqb + sqa *(-b + 0.25);int x = 0;int y = b;EllipsePlot(xc, yc, x, y);while(sqb *(x + 1)< sqa *(y1))* 2-(a * b)* 2;while(y > 0){if(d < 0){ d += sqb *(2 * x + 2)+ sqa *(-2 * y + 3);x++;} else {d += sqa *(-2 * y + 3);} y--;EllipsePlot(xc, yc, x, y);}} 3.2 图形变换的基本原理 3.2.1平移变换 平移变换函数如下: void glTranslate{fd}(TYPE x, TYPE y, TYPE z); 三个函数参数就是目标分别沿三个轴向平移的偏移量。这个函数表示用于这三个偏移量生成的矩阵乘以当前矩阵。当参数是(0.0,0.0,0.0)时,表示对函数glTranslate*()的操作是单位矩阵,也就是对物体没有影响。 3.2.2 旋转变换 旋转变换函数如下: Void glRota{fd}TYPE angle, TYPE x, TYPE y, TYPE z); 函数中第一个参数是表示目标沿从点(x,y,z)到原点方向逆时针旋转的角度,后三个参数是旋转的方向点坐标。这个函数表示用这四个参数生成的矩阵乘以当前矩阵。当角度参数是0.0时,表示对物体没有影响。3.2.3 比例变换 比例变换函数如下: Void glScale{fd}(TYPE x, TYPE y, TYPE z); 单个函数参数值就是目标分别沿三个轴方向缩放的比例因子。这个函数表示用这三个比例因子生成的矩阵乘以当前矩阵。这个函数能完成沿相应的轴对目标进行拉伸、压缩和反射三项功能。以参数x为例,若当x大于1.0时,表示沿x方向拉伸目标;若x小于1.0,表示沿x轴方向收缩目标;若x=-1.0表示沿x轴反射目标。其中参数为负值时表示对目标进行相应轴的反射变换。 四、总体设计与功能实现 4.1 主要界面设计 4.2 设置颜色界面 4.2.1 界面设置代码: void CGraphicsView::OnClock(){ WHAT_TO_DO=ID_CLOCK; clean();int xx = 450, yy = 300, r = 150,d = 5;int i, white = RGB(255,255,255);mile(xx, yy, r, COLOR);Matrix m(xx, 240), s(xx, 200);Matrix t1(xx, yy, true), t2(-xx,-yy, true), mr(PI/1800), sr(PI/30);mile(m.getx(), m.gety(), d+1, COLOR);mile(s.getx(), s.gety(), d, COLOR);dne(m.getx(), m.gety(), xx, yy, COLOR);dne(s.getx(), s.gety(), xx, yy, COLOR); for(i=0;i<120;i++){ ::Sleep(80); mile(m.getx(), m.gety(), d+1, white);mile(s.getx(), s.gety(), d, white);dne(m.getx(), m.gety(), xx, yy, white);dne(s.getx(), s.gety(), xx, yy, white);m = t1*mr*t2*m;s = t1*sr*t2*s;mile(m.getx(), m.gety(), d+1, COLOR);mile(s.getx(), s.gety(),d, COLOR);dne(m.getx(), m.gety(), xx, yy, COLOR);dne(s.getx(), s.gety(), xx, yy, COLOR);}} 4.2.2 点击“设置--颜色”后,运行结果如下: 4.3 二维线画图元实现 4.3.1 实现代码: void CGraphicsView::MidCir(CDC *pdc, int x0, int y0, int x1, int y1, int color){ int r,x,y,deltax,deltay,d;r=sqrt(((double)x1-(double)x0)*((double)x1-(double)x0)+((double)y1-(double)y0)*((double)y1-(double)y0));x=0;y=r;deltax=3;deltay=2-r-r;d=1-r;while(x<=y){ ::Sleep(time); pdc->SetPixel(x+x0,y+y0,color); ::Sleep(time); pdc->SetPixel(-x+x0,y+y0,color); ::Sleep(time); pdc->SetPixel(x+x0,-y+y0,color); ::Sleep(time); pdc->SetPixel(-x+x0,-y+y0,color); ::Sleep(time); pdc->SetPixel(y+x0,x+y0,color); ::Sleep(time); pdc->SetPixel(-y+x0,x+y0,color); ::Sleep(time); pdc->SetPixel(y+x0,-x+y0,color); ::Sleep(time); pdc->SetPixel(-y+x0,-x+y0,color); if(d<0) { d+=deltax; deltax+=2; x++;} else { d+=deltax+deltay; deltax+=2; deltay+=2; x++; y--;}}} void CGraphicsView::midellispse(int xx, int yy, int r1, int r2, int color){ } void CGraphicsView::Ellipse(CDC *pdc, int x1, int y1, int x2, int y2, int color){ xx0=(x2+x1)/2;yy0=(y2+y1)/2;rra=abs(x2-x1)/2;rrb=abs(y2-y1)/2;if(rra==0 && rrb==0)return;Ellipse0(pdc,xx0,yy0,rra,rrb,color);} void CGraphicsView::Ellipse0(CDC *pdc, int x0, int y0, int a, int b, int color){ int i,yy;int x,y,deltax,deltay;int aa,aa2,aa3,bb,bb2,bb3;double d1,d2;aa=a*a;aa2=aa*2;aa3=aa*3;bb=b*b;bb2=bb*2;bb3=bb*3;x=0;y=b;d1=bb+aa*(-b+0.25);deltax=bb3;deltay=-aa2*b+aa2;pdc->SetPixelV(x+x0,y+y0,color);pdc->SetPixelV(x+x0,-y+y0,color);while(bb*(x+1) yy=y; if(d1<0) { d1+=deltax; deltax+=bb2; x++;} else { d1+=deltax+deltay; deltax+=bb2; deltay+=aa2; x++; y--;} ::Sleep(time); pdc->SetPixelV(x+x0,y+y0,color); ::Sleep(time); pdc->SetPixelV(-x+x0,y+y0,color); ::Sleep(time); pdc->SetPixelV(x+x0,-y+y0,color); ::Sleep(time); pdc->SetPixelV(-x+x0,-y+y0,color);} d2=bb*(x+0.5)*(x+0.5)+aa*(y-1)*(y-1)-aa*bb;deltax-=bb;deltay+=aa;while(y>0){ if(d2<0) { d2+=deltax+deltay; deltax+=bb2; deltay+=aa2; x++; y--;} else { d2+=deltay; deltay+=aa2; y--;} ::Sleep(time); pdc->SetPixelV(x+x0,y+y0,color); ::Sleep(time); pdc->SetPixelV(-x+x0,y+y0,color); ::Sleep(time); pdc->SetPixelV(x+x0,-y+y0,color); ::Sleep(time); pdc->SetPixelV(-x+x0,-y+y0,color);}} void CGraphicsView::DDALine(CDC *pdc, int x0, int y0, int x1, int y1, int color){ int xx,yy,s,s1,s2,di;float dx,dy,k,x,y;dx=x1-x0;if(dx>=0) s1=1;else s1=-1;dy=y1-y0;if(dy>=0) s2=1;else s2=-1;dx=abs(dx);dy=abs(dy);if(dx>=dy){ s=0; di=(int)dx; k=dy/dx*s2;} else { s=1; di=(int)dy; k=dx/dy*s1;} x=x0;y=y0;for(int i=0;i<=di;i++){if(s==0) { xx=(int)x; yy=(int)(y+0.5); ::Sleep(time); pdc->SetPixel(xx,yy,color); x+=s1; y+=k;} else{ xx=(int)(x+0.5); yy=(int)y; ::Sleep(time); pdc->SetPixel(xx,yy,color); y+=s2; x+=k;}}} 4.3.2 点击二维线画图元,课相应画出直线、圆和椭圆,结果如下: 4.4 画多边形功能的实现 4.4.1 部分实现代码: void CGraphicsView::OnDrawDuoBX(){ Vertex_Count dlg;if(dlg.DoModal()==IDOK){ if(dlg.m_vertex_count>MAX) { MessageBox(“输入顶点数过大”); return;} VertexTotal=dlg.m_vertex_count; CDC *pDC=GetDC(); CPen pen(PS_SOLID,2,RGB(255,255,255)); CPen *pOldpen=pDC->SelectObject(&pen); pDC->MoveTo((int)(inVertexArray[0].x+0.5),(int)(inVertexArray[0].y+0.5)); int i; for(i=1;i pDC->LineTo((int)(inVertexArray[i].x+0.5),(int)(inVertexArray[i].y+0.5)); pDC->LineTo((int)(inVertexArray[0].x+0.5),(int)(inVertexArray[0].y+0.5)); pDC->SelectObject(pOldpen); ReleaseDC(pDC); inLength=0; outLength=0; WHAT_TO_DO=ID_DrawDuoBX;}} 4.4.2 点击多边形,输入定点个数,可绘制出相应的多边形,结果如下: 4.5 画Bezier曲线功能的实现 4.5.1 部分实现代码: void CGraphicsView::OnBezier(){ // TODO: Add your command handler code here WHAT_TO_DO=ID_BEZIER;CDC *p=GetDC(); p->TextOut(10, 20, “PS:鼠标左键添加曲线,鼠标右键修改曲线.”); ReleaseDC(p);} void CGraphicsView::OnBezierClear(){ n =-1;RedrawWindow();} void CGraphicsView::DrawBezier(DPOINT *p){ if(n <= 0)return;if((p[n].x < p[0].x+1)&&(p[n].x > p[0].x-1)&&(p[n].y < p[0].y+1)&&(p[n].y > p[0].y-1)){ pDC->SetPixel(p[0].x, p[0].y, COLOR); return;} DPOINT *p1;p1 = new DPOINT[n+1];int i, j;p1[0] = p[0];for(i=1;i<=n;i++){ for(j=0;j<=n-i;j++) { p[j].x =(p[j].x + p[j+1].x)/2; p[j].y =(p[j].y + p[j+1].y)/2;} p1[i] = p[0];} DrawBezier(p);DrawBezier(p1);delete p1;} void CGraphicsView::OnBezierAdd(){ AddorMove = 1;} void CGraphicsView::OnBezierMove(){ AddorMove =-1;} void CGraphicsView::OnMouseMove(UINT nFlags, CPoint point){ switch(WHAT_TO_DO){ case ID_BEZIER: { if(current >= 0){ points[current].x = point.x; points[current].y = point.y; RedrawWindow();} if(current2 >= 0) { points[current2].x = point.x; points[current2].y = point.y; RedrawWindow();} break;} default:break;} CView::OnMouseMove(nFlags, point);} 4.5.2 点击曲线--Beizer曲线,可实现Beizer曲线的绘制功能,绘制结果如下图: 图 1 图 2 4.5.3 点击曲线--Beizer曲线,可实现Beizer曲线的移动,鼠标点击其中的任一点,可实现曲线的移动,绘制结果如下图: 上图1移动后的曲线 上图2移动后的曲线 4.6 二维图形变换的实现 可以实现一椭圆在界面上的随机移动,一圆在界面上饶某一点的旋转和一正方形由大变小在变大的变化,部分实现代码如下: void CGraphicsView::OnXuanzhuan(){ WHAT_TO_DO=ID_XUANZHUAN; time=0; OnClear(); CClientDC dc(this);CDC* pDC=&dc; int i, white=RGB(255,255,255), point [2][2]={{300,200},{300,250}}; Matrix a(point[0][0],point[0][1]), b(point[1][0],point[1][1]); int midx=(point[0][0]+point[1][0])/2,midy=(point[0][1]+point[1][1])/2; Matrix t1(midx, midy,true), t2(-midx,-midy,true); Matrix r(PI/50); Matrix temp(midx, midy,true); temp = t1*r*t2; for(i=0;i<200;i++){ ::Sleep(50); MidCir(pDC, a.getx(), a.gety(), b.getx(), b.gety(), white); a = temp*a; b = temp*b; MidCir(pDC, a.getx(), a.gety(), b.getx(), b.gety(), COLOR);} for(i=0;i<200;i++){ ::Sleep(50); MidCir(pDC,a.getx(), a.gety(), b.getx(), b.gety(), white); a = temp*a; b = temp*b; MidCir(pDC, a.getx(), a.gety(), b.getx(), b.gety(), COLOR);} time=5;} void CGraphicsView::OnUpdateXuanzhuan(CCmdUI* pCmdUI){ pCmdUI->SetCheck(WHAT_TO_DO==ID_XUANZHUAN);} void CGraphicsView::OnScale(){ WHAT_TO_DO=ID_SCALE; OnClear();CClientDC dc(this);CDC* pDC=&dc; time=0;int i,white=RGB(255,255,255), point[4][2]={{300,250},{400,250},{300,300},{400,300}};float sx=0.9,sy=0.85;int midx=(point[0][0]+point[3][0])/2,midy=(point[0][1]+point[3][1])/2;Matrix s1(sx,sy),s2(1/sx,1/sy);Matrix t1(midx, midy,true), t2(-midx,-midy,true); Matrix a(point[0][0],point[0][1]), b(point[1][0],point[1][1]);Matrix c(point[2][0],point[2][1]), d(point[3][0],point[3][1]);Matrix temp(midx, midy,true);temp = t1*s1*t2;DDALine(pDC,a.getx(),a.gety(),b.getx(),b.gety(),COLOR);DDALine(pDC,a.getx(),a.gety(),c.getx(),c.gety(),COLOR);DDALine(pDC,c.getx(),c.gety(),d.getx(),d.gety(),COLOR);DDALine(pDC,d.getx(),d.gety(),b.getx(),b.gety(),COLOR);for(i=0;i<20;i++){ ::Sleep(30); DDALine(pDC,a.getx(),a.gety(),b.getx(),b.gety(),white); DDALine(pDC,a.getx(),a.gety(),c.getx(),c.gety(),white); DDALine(pDC,c.getx(),c.gety(),d.getx(),d.gety(),white); DDALine(pDC,d.getx(),d.gety(),b.getx(),b.gety(),white); a=temp*a; b=temp*b; c=temp*c; d=temp*d; DDALine(pDC,a.getx(),a.gety(),b.getx(),b.gety(),COLOR); DDALine(pDC,a.getx(),a.gety(),c.getx(),c.gety(),COLOR); DDALine(pDC,c.getx(),c.gety(),d.getx(),d.gety(),COLOR); DDALine(pDC,d.getx(),d.gety(),b.getx(),b.gety(),COLOR);} temp = t1*s2*t2;for(i=0;i<20;i++){ ::Sleep(30); DDALine(pDC,a.getx(),a.gety(),b.getx(),b.gety(),white); DDALine(pDC,a.getx(),a.gety(),c.getx(),c.gety(),white); DDALine(pDC,c.getx(),c.gety(),d.getx(),d.gety(),white); DDALine(pDC,d.getx(),d.gety(),b.getx(),b.gety(),white); a=temp*a; b=temp*b; c=temp*c; d=temp*d; DDALine(pDC,a.getx(),a.gety(),b.getx(),b.gety(),COLOR); DDALine(pDC,a.getx(),a.gety(),c.getx(),c.gety(),COLOR); DDALine(pDC,c.getx(),c.gety(),d.getx(),d.gety(),COLOR); DDALine(pDC,d.getx(),d.gety(),b.getx(),b.gety(),COLOR);} time=5;} void CGraphicsView::OnUpdateScale(CCmdUI* pCmdUI){ pCmdUI->SetCheck(WHAT_TO_DO==ID_SCALE);} 4.7 三维图形的变换 主要实现三维图形的上下左右平移,分别绕X轴Y轴Z轴的旋转,放大和缩小,以及正方体六个面的颜色变换,除此之外,还可以选择背景颜色的改变 4.7.1 部分代码如下: void CGraphicsView::OnAoduomianti(){ WHAT_TO_DO=ID_AODUOMIANTI;CDrawDLG dlg1;dlg1.DoModal();} void CGraphicsView::OnUpdateAoduomianti(CCmdUI* pCmdUI){ pCmdUI->SetCheck(WHAT_TO_DO==ID_AODUOMIANTI);} void CDrawDLG::OnPaint() { CPaintDC dc(this);// device context for painting CWnd *pWnd=GetDlgItem(IDC_DRAW);pWnd->UpdateWindow();// CDC *PDC=pWnd->GetDC();Draw();} void CDrawDLG::Draw(){ CWnd *pWnd=GetDlgItem(IDC_DRAW);pWnd->UpdateWindow();CDC *pDC=pWnd->GetDC();CRect rect;pWnd->GetClientRect(rect);D v[8]={ {-fs,-fs,fs},{-fs,fs,fs},{fs,fs,fs},{fs,-fs,fs},{-fs,-fs,-fs},{-fs,fs,-fs},{fs,fs,-fs},{fs,-fs,-fs} },d[8]; POINT p0[4],p1[4],p2[4],p3[4],p4[4],p5[4],w[8];int z[8]; for(int i=0;i<8;i++){ d[i].x=v[i].x; d[i].y=(int)(v[i].y*cos(a*DU)-v[i].z*sin(a*DU)); d[i].z=(int)(v[i].y*sin(a*DU)+v[i].z*cos(a*DU)); v[i].x=(int)(d[i].x*cos(b*DU)+d[i].z*sin(b*DU)); v[i].y=d[i].y; v[i].z=(int)(d[i].z*cos(b*DU)-d[i].x*sin(b*DU)); d[i].x=(int)(v[i].x*cos(c*DU)-v[i].y*sin(c*DU)); d[i].y=(int)(v[i].x*sin(c*DU)+v[i].y*cos(c*DU)); d[i].z=v[i].z; w[i].x=d[i].x+cx; w[i].y=d[i].y+cy; z[i]=d[i].z;} p0[0]=w[0];p0[1]=w[1];p0[2]=w[2];p0[3]=w[3];p1[0]=w[4];p1[1]=w[5];p1[2]=w[6];p1[3]=w[7]; p2[0]=w[0];p2[1]=w[1];p2[2]=w[5];p2[3]=w[4];p3[0]=w[1];p3[1]=w[2];p3[2]=w[6];p3[3]=w[5];p4[0]=w[2];p4[1]=w[3];p4[2]=w[7];p4[3]=w[6];p5[0]=w[0];p5[1]=w[3];p5[2]=w[7];p5[3]=w[4];switch(Maxnum(z,7)){ case 0:fill(p0,p2,p5,0,2,5);break; case 1:fill(p0,p2,p3,0,2,3);break; case 2:fill(p0,p3,p4,0,3,4);break; case 3:fill(p0,p4,p5,0,4,5);break; case 4:fill(p1,p2,p5,1,2,5);break; case 5:fill(p1,p2,p3,1,2,3);break; case 6:fill(p1,p3,p4,1,3,4);break; case 7:fill(p1,p4,p5,1,4,5);break;}} BOOL CDrawDLG::OnInitDialog(){ CDialog::OnInitDialog();m_scroll1.SetScrollRange(-180,180);m_scroll1.SetScrollPos(0);m_scroll2.SetScrollRange(-180,180);m_scroll2.SetScrollPos(0);m_scroll3.SetScrollRange(-180,180);m_scroll3.SetScrollPos(0);m_scroll4.SetScrollRange(0,350);m_scroll4.SetScrollPos(200);m_scroll5.SetScrollRange(0,300);m_scroll5.SetScrollPos(115);m_scroll6.SetScrollRange(0.00,300.00);m_scroll6.SetScrollPos(50.00);a=b=c=0;fs=50.00;SetTimer(1,100,NULL);Ctrl=0;cx=200;cy=115;COLOR1=RGB(123,234,43);COLOR2=RGB(123,123,0);COLOR3=RGB(123,24,235);COLOR4=RGB(0,123,95);COLOR5=RGB(23,234,34);COLOR6=RGB(234,124,0);COLOR7=RGB(0,43,98);return TRUE;// return TRUE unless you set the focus to a control} void CDrawDLG::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar){ int nID=pScrollBar->GetDlgCtrlID();switch(nID){ case IDC_SCROLLBAR1: a=pScrollBar->GetScrollPos(); switch(nSBCode) { case SB_LINELEFT: a--;break; case SB_LINERIGHT: a++;break; case SB_PAGELEFT: a-=10;break; case SB_PAGERIGHT: a+=10;break; case SB_THUMBTRACK: a=nPos;break;} if(a<-180)a=180; if(a>180)a=-180; pScrollBar->SetScrollPos(a); break;case IDC_SCROLLBAR2: b=pScrollBar->GetScrollPos(); switch(nSBCode) { case SB_LINELEFT: b--;break; case SB_LINERIGHT: b++;break; case SB_PAGELEFT: b-=10;break; case SB_PAGERIGHT: b+=10;break; case SB_THUMBTRACK: b=nPos;break;} if(b<-180)b=180; if(b>180)b=-180; pScrollBar->SetScrollPos(b); break;case IDC_SCROLLBAR3: c=pScrollBar->GetScrollPos(); switch(nSBCode) { case SB_LINELEFT: c--;break; case SB_LINERIGHT: c++;break; case SB_PAGELEFT: c-=10;break; case SB_PAGERIGHT: c+=10;break; case SB_THUMBTRACK: c=nPos;break;} if(c<-180)c=180; if(c>180)c=-180; pScrollBar->SetScrollPos(c); break;case IDC_SCROLLBAR4: cx=pScrollBar->GetScrollPos(); switch(nSBCode) { case SB_LINELEFT: cx--;break; case SB_LINERIGHT: cx++;break; case SB_PAGELEFT: cx-=10;break; case SB_PAGERIGHT: cx+=10;break; case SB_THUMBTRACK: cx=nPos;break;} if(cx<0)cx=200; if(cx>350)cx=200; pScrollBar->SetScrollPos(cx); break;case IDC_SCROLLBAR5: cy=pScrollBar->GetScrollPos(); switch(nSBCode) { case SB_LINELEFT: cy--;break; case SB_LINERIGHT: cy++;break; case SB_PAGELEFT: cy-=10;break; case SB_PAGERIGHT: cy+=10;break; case SB_THUMBTRACK: cy=nPos;break;} if(cy<0)cy=300; if(cy>300)cy=0; pScrollBar->SetScrollPos(cy); break; case IDC_SCROLLBAR6: fs=pScrollBar->GetScrollPos(); switch(nSBCode) { case SB_LINELEFT: fs--;break; case SB_LINERIGHT: fs++;break; case SB_PAGELEFT: fs-=0.55;break; case SB_PAGERIGHT: fs+=0.55;break; case SB_THUMBTRACK: fs=nPos;break;} if(fs<0)fs=50; if(fs>300)fs=50; pScrollBar->SetScrollPos(fs); break;// UpdateData(FALSE);} // Invalidate();Draw();CDialog::OnHScroll(nSBCode, nPos, pScrollBar);} void CDrawDLG::OnOK(){ KillTimer(1); CDialog::OnOK();} int CDrawDLG::Maxnum(int *p, int n){ int max=p[0];int x;for(int i=0;i<=n;i++){ if(max<=p[i]) { max=p[i];x=i;} } return x;} void CDrawDLG::fill(POINT *x, POINT *y, POINT *z, int i,int j,int q){ CWnd *pWnd=GetDlgItem(IDC_DRAW);pWnd->UpdateWindow();CDC *pDC=pWnd->GetDC();CRect rect;pWnd->GetClientRect(rect); CDC dcmem;dcmem.CreateCompatibleDC(pDC);CBitmap bmp,*oldbmp;bmp.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());oldbmp=dcmem.SelectObject(&bmp);CBrush brush[6];brush[0].CreateSolidBrush(COLOR1);brush[1].CreateSolidBrush(COLOR2);brush[2].CreateSolidBrush(COLOR3);brush[3].CreateSolidBrush(COLOR4);brush[4].CreateSolidBrush(COLOR5);brush[5].CreateSolidBrush(COLOR6);CBrush *oldbrush=dcmem.SelectObject(&brush[i]);dcmem.FillSolidRect(rect,COLOR7);dcmem.Polygon(x,4);dcmem.SelectObject(&brush[j]);dcmem.Polygon(y,4);dcmem.SelectObject(&brush[q]);dcmem.Polygon(z,4);dcmem.SelectObject(oldbrush);for(int b=0;b<6;b++)brush[b].DeleteObject();pDC->BitBlt(rect.left,rect.top,rect.Width(),rect.Height(), &dcmem,0,0,SRCCOPY);dcmem.SelectObject(oldbmp);bmp.DeleteObject();dcmem.DeleteDC();} 4.7.2 运行结果如下: (1)实现多面体的上下左右平移(2)实现多面体的绕轴旋转: (3)实现多面体的放大缩小: (4)实现多面体及背景的颜色设置: (5)三维图形变换整体图形 五、实验心得体会 在本次课程设计过程中,基本掌握了计算机图形学关于图形绘制变换的基础知识,DDA法画直线和中心点法画圆及椭圆的方法,还对图形的变换及需要用到的一系列的函数有了相应的理解,也了解的很多有关于图形学中三维图形的变换的知识。不过都只是皮毛而已,从中锻炼了自己的动手做实验的能力,但同时也让自己看清了自己的水平,以便在以后的生活里多加强有关这方面的学习,从而提升自己在图形学方面的知识水平。 在本次课程设计中,设计方案存在着很多的死板化的实现方法,也是很不人性化的一点,只提供了画一种曲线的方法,且画出的曲线只能移动,此为本次设计方案的不足之一;然后就是能实现曲面和多边形的绘制,却没有对应的实现绘制好图形后直接对其进行平移、选择等变换,此为设计方案不足之二。再者就是三维图形只能实现变换不能实现绘制,此为设计方案不足之三。鉴于个人能力真的有限,所以只能设计出此种级别的效果了。因为实验重要的只是思想过程,效果的不美观只能是因为学习的知识还远远不够,所以不能设计出完美的全面的图形绘制变换程序。 计算机图形学课程教学探析 本文结合计算机图形学的`教学特点,从提高学生的兴趣入手,从教学方法、教学内容等方面,提出了表学模式改革方案,从而适应计算机教育的发展. 周迎春(蚌埠坦克学院,安徽蚌埠,233050) 一、目前教学中存在的问题 《计算机图形学》课程是一门理论与实践结合性强的课程, 这导致在实际教学过程中存在以下四个问题。 1. 教与学的目的不统一。 笔者通过教学过程中与学生的交流发现, 大部分学生对本课程的理解不是很正确。他们之所以选修这门课程, 主要是因为他们认为通过对《计算机图形学》的学习可以处理漂亮的图片、制作炫目的动画和进行游戏编程等。然而该课程实际上是去探究实现这些操作的原理, 是研究更本质的知识。学生一开始对该课程充满好奇和期待, 但随着课程的深入讲解, 他们会感到本课程的理论知识枯燥, 导致学习兴趣不断下降。 2. 学生动手能力的不足。 《计算机图形学》这门课程要求学生具有较强的编程能力和动手能力, 因为要掌握和实现一些图形学基本算法。而在教学中发现, 大部分学生的编程能力和动手能力都一般, 很多任务不能正常完成, 从而间接打击了学生的积极性, 使得他们对该课程的兴趣与日递减, 最后转为放弃学习。 3. 课程设置不合理。 《计算机图形学》尽管是计算机科学的一门重要学科, 但在计算机科学与技术专业并不是核心课程, 因此在课程设置中只是将该课程作为高年级的方向选修课开设。很大部分选修学生不是真心想学习该课程, 再加上这些学生对课程的理解也存在着偏颇。基于这个现状, 任课教师也就只能在实际授课时力求简单, 从而导致教师无法完成必需的教学内容。 4. 实践教学重视不够。 传统教学模式只重视理论而忽视实践, 一方面表现在实践课时安排上 (本校课堂教学的课时是实践教学的两倍) ;另一方面是开设的实验更多的只是算法验证性实验。这使得原本很重要的实践活动转变为形式, 这势必阻碍学生运用所学图形学理论知识提升其自身的创新能力。 二、教学改革具体措施 1. 板书与多媒体相结合。 多媒体教学作为现代教育的有效手段, 确实具有传统教学无法比拟的优势, 它信息量大、效率高、趣味性强, 使教师的授课更便捷, 让算法的演示更形象具体, 从而有利于激发学生的学习热情, 使教学效果达到最优化。因此, 目前基本上所有的高校都采用多媒体方式进行授课。但其实对于图形学这门课程, 由于其涉及到大量的数学推导, 比如, 基本图形的生成、图形几何变换和曲线曲面造型等, 在多媒体教学的同时, 需要运用板书进行相关数学推导, 这可以使学生在教师板书的过程中学会思考, 从而更好、更正确地理解各种图形算法。 2. 加强实例教学。 由于图形学课程需要掌握很多算法, 因此在讲解图形学算法时, 不能只讲理论, 这样太空洞。应围绕具体的实例进行教学, 借助计算机技术 (比如flash) 对一些算法进行动画模拟演示, 从而使算法的描述更加形象化和具体化。这一方面有利于学生更快更好的掌握这些算法;另一方面也可以激发学生学习的热情和积极性。比如, 在讲解“多边形填充4连通边界填充算法”时, 利用flash演示像素入栈出栈原理, 如图1所示, 更直观地展示算法的基本思想, 从而充分调动了学生的学习积极性, 使其具备主动学习的能力。不过因为课时有限, 演示实例不能太复杂, 能把算法讲解清楚即可。 注:邻接点按字母A、B、C顺序入栈, 同一像素点用一数字表示和入栈。 (1) 栈顶像素出栈。 (2) 将出栈像素置为填充颜色。 (3) 检查出栈像素的4-邻接点, 若某像素点既非边界点且未置为填充色, 则该像素入栈。 3. 加强实践能力的培养。 《计算机图形学》理论和算法是比较深奥和难懂的, 不是很容易掌握, 但其实验结果却是直观和生动的。该课程具有很强的实践性和应用性, 因此上机实验是其重要环节。在教学过程中需要继续加强学生实践能力的培养, 引导学生把所学的基本理论知识应用于实践操作, 不断提高学生发现问题、分析问题和解决问题的能力。《计算机图形学》在本校的总学时数为48学时, 其中的实验课时数为14学时, 这14个学时7次实验基本能够满足课程实践教学的需要。本课程的实验根据难易程度可分为如下两个层次[3]: (1) 基本实验。主要是为了锻炼学生对算法的理解能力、算法到程序的转换能力以及用VC编程实现算法的能力, 主要包括基本图形 (直线、圆和椭圆) 算法、线型和线宽的处理、字符的生成技术、线段的裁剪、二维和三维图形的几何变换和投影变换、曲线绘制等, 要求学生能够独立完成。 (2) 综合实验。这类实验包括多边形裁剪算法、多边形区域填充算法、区域图案填充算法、多面体的消影、画家隐面算法和Z-Buffer隐面算法等, 它们无论从算法复杂性上还是程序编写难度上都要高于基本实验。可以考虑将学生分成若干小组, 以小组的形式在规定的时间内完成。 参考文献 [1]陆枫, 何云峰.计算机图形学基础 (第2版) [M].北京:电子工业出版社, 2011. [2]曲福恒, 胡雅婷“.计算机图形学”教学改革初探[J].长春理工大学学报, 2011, 6 (9) :184-185. 【计算机图形学实验报告】推荐阅读: 计算机实验报告模板07-08 计算机实验报告一08-04 计算机原理实验报告三09-12 化学计算实验习题07-26 计算机组网技术与应用实验考试题目及要求08-19 2022年公共计算机教学实验中心工作计划09-04 高中化学必学计算08-05 重邮计算机网络实验总结07-17 《计算机网络》课程实验教学大纲08-12 计算机操作系统报告09-072.计算机图形学实验报告 篇二
3.计算机图形学教学改革浅论 篇三
4.计算机图形学实验报告 篇四
5.计算机图形学课程教学探析 篇五
6.《计算机图形学》教学改革初探 篇六