第一篇:图形学教案ch1.ppt.Convertor范文
计算机图形学第一章 绪论
第一章
绪论
计算机图形学(Computer Graphics)
使用计算机建立、存储、处理某个具体的或抽象的对象的模型,并根据该模型产生该对象的图形输出的有关理论、方法和技术叫做计算机图形学。是计算机科学中最为活跃、得到广泛应用的分支之一。
计算机图形学的主要研究内容
图形硬件、图形标准、图形交互技术、光栅图形生成算法、曲线曲面造型、实体造型、真实感图形计算与显示算法,以及科学计算可视化、计算机动画、自然景物仿真、虚拟现实等。图形与图象
图象纯指计算机内以位图(Bitmap)形式存在的灰度信息。图形含有几何属性,更强调场景的几何表示,是由场景的几何模型和景物的物理属性共同组成的。
图形主要分为两类
基于线条信息表示。如工程图、等高线地图、曲面的线框图等。明暗图(Shading)。即是通常所说的真实感图形。
图形软件的分类
专用图形(应用)软件包和通用图形程序设计软件包。
专用软件包的接口通常是一组菜单,用户通过菜单与程序进行通信。例如,3DMAX、PHOTOSHOP、各种CAD系统等等。
通用软件包提供了一个可用于C、C++、JAVA等高级语言的图形函数库。该图形库提供了用来描述基本图元(如直线段、多边形、球面、样条曲线等)、设定颜色、场景的观察以及对象的各种变换等的基本函数。例如,GKS(图形核心系统)、PHIGS(程序员层次交互式图形系统)、GL(图形程序库)、OpenGL(开放式图形库)、GIL(清华大学CAD中心开发)、VRML(Virtual-Reality Modeling Language,虚拟现实建模语言)等等。
计算机图形学的发展历史 1、50年代的准备和酝酿时期。2、60年代的确立和蓬勃发展时期。3、70年代的实用化时期。4、80年代的普及时期。5、90年代的标准化、集成化、智能化时期。
图形硬件设备 显示器:
目前应用最普及的是基于阴极射线管(CRT)的光栅扫描显示器。阴极射线管(CRT)主要由电子枪、聚焦系统、加速电极、偏转系统和荧光屏五部分组成。
随机扫描显示器
随机扫描显示器中的电子束的定位和偏转具有随机性。要显示的图形的定义是存放在刷
1/5
计算机图形学第一章 绪论
新缓存的一组画线命令。系统周期性地执行刷新缓存中的一组命令,根据当前的线条走向,由显示控制器控制电子束的偏移,依次画出其组成线条,从而在屏幕上产生图形;当所有画线命令处理完后,系统周期地返回到该刷新缓存的第一条画线命令。因此,随机扫描显示器是画线式显示器,或矢量式显示器。
存储管式显示器
缺点:不能用存储管式显示器产生动画。存储管式显示器是画线设备。
光栅扫描显示器
光栅扫描方式将CRT屏幕分成由像素构成的光栅网格,其中像素具有灰度和颜色;所有像素的灰度和颜色信息(也称为显示内容)保存在一个专门的内存区域中,称为帧缓冲存储器(Frame Buffer),简称帧缓存。帧缓存的深度(位面数),即每个像素的位数决定了某一个显示系统能显示的颜色数。例如,1位深度帧缓存只能显示两种颜色,而8位深度帧缓存可以显示28(=256)种颜色。在全色彩(full-color)系统里,深度为24位的图形系统可以显示足够多的颜色数,能表示大多数真实感图像,所以称之为真彩色(true-color)系统。
在光栅扫描显示器中,一幅图像是由像素(pixel)阵列组成,而像素的阵列称为光栅(raster)。一幅图像的像素全部存放在一个称为帧缓存器的内存里。帧缓存的深度(位面数),即每个像素的位数决定了某一个显示系统能显示的颜色数。例如,1位深度帧缓存只能显示两种颜色,而8位深度帧缓存可以显示(2=256)种颜色。在全色彩(full-color)系统里,深度为24位的图形系统可以显示足够多的颜色数,能表示大多数真实感图像,所以称之为真彩色(true-color)系统。
黑白单灰度光栅扫描显示器 黑白多灰度光栅扫描显示器 彩色单灰度光栅扫描显示器 彩色多灰度光栅扫描显示器
2/5
计算机图形学第一章 绪论
一个具有24位面的帧缓冲存储器,红、绿、蓝各8个位面,其值经数模转换控制红、绿、蓝电子枪的强度,每支电子枪的强度有256(8位)个等级,则能显示256*256*256=16兆种颜色,16兆种颜色也称作(24位)真彩色。从以上的讨论我们知道,像素的颜色数和帧缓存的大小是成正比的。为了节制帧缓存的增加,用尽量少的帧缓存来得到尽可能多的颜色数,提出了一种技术——查找表技术。
液晶显示器(Liquid Crystal Display,简称LCD)
利用液晶的物理特性,通电时导通,晶体在电场作用下,排列变得有秩序,通过它的光的折射角度会发生变化,使光线容易通过;不通电时,晶体排列变得混乱,光被遮挡,不能通过。
等离子显示器(Plasma Display Panel,简称PDP)
利用气体放电激发荧光粉发光的显示装置。等离子管作为等离子显示器的发光元件,大量的等离子管排列在一起构成屏幕。
平板显示器具有超薄超轻、无辐射、低功耗等优良特性,近几年来正在逐步普及。
刷新式随机扫
随机扫描显示器 CRT显示器(刷新式)光栅
存储管式显示器
图形显示器
液晶显示器(LCD)
平板显示器 等离子显示器(PDP)
图形绘制设备
1.绘图仪
笔式绘图仪(画线设备)静电绘图仪(画点设备)
2.打印机(画点设备)点阵式打印机 喷墨打印机 激光打印机
常见的两种颜色模型
RGB颜色模型
在这种颜色系统中,每一种基色的亮度可以从0到1,通过混合不同亮度的三种基色(红、3/5
计算机图形学第一章 绪论
绿、蓝)可以表示多种颜色。由黑色开始,接着加入合适的基色得到希望的颜色。即RGB颜色系统是一个加色系统。
图形显示器使用的是RGB颜色系统。有红、绿、蓝三个电子枪,每个基色的亮度由调整电子枪轰击荧光屏的强度获得,通过混合不同亮度的三种基色可以在显示器上得到相应的颜色。
CMY颜色模型
在CMY颜色模型中,由白色开始,接着减去合适的基色元素得到希望的颜色。CMY颜色系统是一个减色系统。例如,从白色中减去红色就得到青色,减去绿色就得到品红,减去兰色就得到黄色等等。绘图设备(如彩色喷墨打印机)使用的就是CMY颜色系统。
RGB颜色系统和CMY颜色系统的关系 例如,在CMY中,(1,1,1)表示黑颜色,而在RGB中,(0,0,0)表示黑颜色。(转换公式见左下图)例如,在CMY颜色模型中,(0,0,1)代表黄色,利用前面的转换公式知道,在RGB颜色模型中,(1,1,0)表示黄色。因此红色和绿色的混合产生黄色,因为投射光中的蓝色成分被吸收了。
再如,在CMY颜色模型中,(1,1,0)表示青色和品红墨水的混合,由转换公式知,生成的颜色为蓝色。这说明自然光投射到青色和品红混合的墨水上时,光线中的红色和绿色成分都被吸收了。
图形输入设备
第一阶段:控制开关、穿孔纸等等
第二阶段:键盘
第三阶段:二维定位设备
如鼠标、光笔、图形输入板、触摸屏、扫描仪 第四阶段:三维输入设备
R1CG1M,B1Y1R1G1BC
如空间球、数据手套、数据衣 M图形系统
Y一个计算机图形系统包括图形硬件系统和图形软件系统。图形硬件系统应包括
(1)显示处理器。(2)显示存储器。(3)帧缓存器。(4)图形输出设备。(5)图形输入设备。图形软件系统应包括专用的图形软件包(Photoshop、3DMAX、各种CAD等等)和通用的图形(编程)软件包(GKS、PHIGS、GL、OpenGL、GIL、VRML等等)。
计算机图形学软件系统
计算机图形学软件系统发展到目前已经非常丰富了,大致可以分为三类:
1、用某种高级语言写成的子程序包*。
2、扩充某一种计算机语言,使其具有图形的生成和处理功能。
3、专用的高级图形语言。
*简单的图形系统有Photoshop、3DMAX、各种CAD等等。复杂的图形系统有GKS、PHIGS、GL、OpenGL、GIL等等。
4/5
计算机图形学第一章 绪论
图形处理器
为了提高显示系统的显示能力和处理图形的速度,以后发展的图形处理器都增加了显示处理器(显示主芯片)GPU,具有很强的图形处理功能。大大减轻了CPU的负担,也提高了图形显示能力和速度。
GPU是图形处理器的核心,其处理图形的能力决定了图形处理器的性能,一个好的3D卡支持硬件加速功能以及各种纹理渲染能力等。
显示处理存储器也称为显存。用于存储将要显示的图形信息以及保存图形运算的中间结果。它与GPU的关系就如同计算机的内存与CPU的关系一样密不可分,显存的大小和存取速度直接影响GPU性能的发挥。
详细内容参见教材P24—P33
5/5
第二篇:图形学教案ch2.ppt.Convertor
计算机图形学第二章 Turbo C的图形功能
第二章
Turbo C 的图形功能
图形显示器的两种显示模式:
文本模式和图形模式
在文本方式下,屏幕上可显示的最小单位是字符。文本方式设置不同,可显示的字符的列数、行数也不相同(在一般缺省方式下,为25行、80列),颜色也有所区别。
在图形方式下,屏幕上可以控制的单位叫做像素,它是组成图形的基本元素,一般也成为“点”。分辨率越高,屏幕上包含的像素个数就越多,显示的图形越细,质量就越好。
屏幕上每个像素的位置可以用该像素在屏幕坐标系中的坐标进行描述。
屏幕坐标系是一个左手系,屏幕左上角为坐标系的原点(0,0),水平方向为X轴,自左向右;垂直方向为Y轴,自上而下。坐标范围与显示器的分辨率有关,例如,当分辨率为640×480时,左上角坐标为(0,0),右下角坐标为(639,479)。
一、图形初始化及应用设置函数
因为在文本方式下不能显示图形,所有的图形函数均不能操作,因此在使用图形函数进行绘图之前,必须将显示适配器设置为图形模式,即通常所说的“图形模式初始化”。在绘图结束之后,又要让适配器的设置回到文本模式。Turbo C提供了14个函数,进行图形系统的控制和管理工作。最常见的两个函数是:
1、初始化图形系统函数
void far initgraph(gdrive,gmode,gpath)int far *gdrive, *gmode, *gpath;gdrive:图形驱动器代号,gmode:图形模式代号,gpath: 图形驱动程序路径。如:常用方式:
int gdrive,gmode;gdrive=DETECT;initgraph(&gdrive,&gmode, “d:tc”);
2、释放图形系统所分配的内存、恢复屏幕原显示模式函数
void far closegraph(void)调用形式:closegraph();
二、屏幕管理函数
1、擦除整个图形屏幕,并将cp(当前位置)移到原点(0,0)
void far cleardevice(void)
2、建立视区
void setviewport(x1,y1,x2,y2)
3、清除视图区
清除视图区用函数clearviewport。它的作用是清除掉当前的视图区,将当前点的位置重新设
1/7
计算机图形学第二章 Turbo C的图形功能
置为屏幕左上角(0,0)。其调用格式为:
clearviewport();
三、常用的作图函数
1、画点函数
putpixel(int x, int y, int color)
2、以当前颜色、线型、宽度画直线函数
void line(x0, y0, x, y)
int x0, y0, x, y;从(x0,y0)画到(x,y)。
3、以当前颜色、线型、宽度画直线函数
void far lineto(int x, int y)从当前点(cp)画到(x,y)。
4、得到当前位置坐标函数
(1)int far getx(void)
返回x坐标
(2)int far gety(void)
返回y坐标
5、以当前颜色、线型、线宽画一矩形函数
void far rectangle(left, top, right, bottom)int left, top, right, bottom;
6、以当前填充模式、填充颜色画一矩形函数
void far bar(left, top, right, bottom)int left, top, right, bottom;
7、以当前填充模式、填充颜色画一多边形函数
void far fillpoly(int num, int a[ ])num:顶点数;
a[ ]:存放各顶点坐标,共num*2个数;若是封闭的,则有num+1个点,有(num+1)*2个数。
8、以当前颜色、线型、线宽画圆函数
void far circle(int x, int y, int radius)x, y:圆心坐标; radius:半径。
9、以当前颜色、线型、线宽画椭圆弧函数
void far ellipse(x, y, stangle, endangle, xradius, yradius)int x, y, stangle, endangle, xradius, yradius;x, y:椭圆中心坐标;
endangle, endangle:画椭圆的起始角和终止角。若endangle=0, endangle=360,则画一完整椭圆。
xradius,yradius:为x、y方向的轴长半径。
10、以当前颜色、线型、线宽及填充模式、填充颜色画扇形函数
void far piselice(x, y, stangle, endangle, radius)若stangle=0, endangle=360,则画一完整圆。
2/7
计算机图形学第二章 Turbo C的图形功能
四、图形属性控制函数
1、得到背景颜色数值函数
int far getbkcolor(void)常调用形式: oldbkcolor=getbkcolor();
2、得到当前绘图颜色数值函数
int far getcolor(void)常调用形式: oldcolor=getcolor();
3、设置背景颜色函数
void far setbkcolor(int color)调用形式如: setbkcolor(BLUE);
(兰色背景)
4、设置当前绘图颜色函数
void far setcolor(int color)调用形式如: setcolor(RED);
(红色绘图颜色)
5、获得最大颜色数函数
int far getmaxcolor(void)调用形式如: maxclor= getmaxcolor();关于颜色值、符号常量与颜色的对应关系 符号常量
数值
颜色 BLACK
0
BLUE
GREEN
CYAN
青 RED
MAGENTA
品红 BROWN
棕色 LIGHTGRAY
灰白 DARKGRAY
灰 LIGHTBLUE
LIGHTGREEN
LIGHTCYAN
浅青 LIGHTRED
LIGHTMAGENTA
浅品红(淡紫色)YELLOW
WHITE
例
1、用16种不同的颜色显示16条不同的线段 #include“graphics.h“
/*hhj01.c*/ main(){ int gdriver=DETECT,gmode;int i,y=0;initgraph(&gdriver,&gmode,”d: urboc2“);for(i=0;i<16;i++)
3/7
计算机图形学第二章 Turbo C的图形功能
{ setcolor(i);line(10,10+y,100,10+y);y+=5;} getch();closegraph();}
例、用直线生成(直纹)曲面
#include”graphics.h“
/*pattern.c*/ main(){ int y;long x;int gdriver=DETECT,gmode;initgraph(&gdriver,&gmode,“d: urboc2”);cleardevice();setbkcolor(9);setcolor(4);for(y=0;y<=240;y+=5){
x=320/240*y;
line(0,y,x,240);
}
getch();
closegraph();
}
6、设置画线宽度和线型的函数
void far setlinestyle(linestyle, upattern, thickness)
int linestyle, thickness;
unsigned upattern;linestyle(线型)取值,0:实线,1:点,2:长短,3:长虚线,4:自定义线型。thickness(宽度)取值: 1、3。
upattern:当linestyle为4时起作用。其他4种预定义情况可取0。例、显示turbo c固有的画线模式 /*line_style01.c*/ #include“graphics.h” main(){ int i,y=0,gdriver=DETECT,gmode;initgraph(&gdriver,&gmode,“d: urboc2”);for(i=0;i<4;i++){
4/7
计算机图形学第二章 Turbo C的图形功能
setcolor(i+1);setlinestyle(i,0,1);line(10,100+y,100,100+y);y+=5;} getch();closegraph();}
例、用自定义线形画线。/*line_style02.c*/ #include“graphics.h” main(){ int gdriver=DETECT,gmode;unsigned upattern=0XEBAE;initgraph(&gdriver,&gmode,“d: urboc2”);setcolor(1);setlinestyle(4,upattern,3);rectangle(100,100,300,300);getch();closegraph();}
7、设置着色(填充)模式和颜色函数
void far setfillstyle(int pattern, int color)pattern(着色模式)取值: 0:用背景颜色填充,1:用纯色填充,2~12:用各种线型和色点填充。
color: 填充颜色。
8、填充封闭区域函数
void far floodfill(x, y, color)int x, y, color;x, y : 填充封闭区域中的一点;color:封闭区域的边界颜色。/*bar3d.c* / #include“graphics.h“ main(){ int gdriver=DETECT,gmode;initgraph(&gdriver,&gmode,”d: urboc2“);setcolor(3);setfillstyle(7,1);bar(200,200,300,300);getch();closegraph();}
5/7
计算机图形学第二章 Turbo C的图形功能
#include”graphics.h“ main(){ int i,gdriver=DETECT,gmode;initgraph(&gdriver,&gmode,”d: urboc2“);setfillpattern(8,RED);setcolor(YELLOW);circle(200,200,100);floodfill(200,200,YELLOW);
/*pattern.c*/ getch();closegraph();}
9、设置用户自定义的填充模式
void
setfillpattern(char *upattern,int color);其中,upattern是指针,指向8个字节,组成用户定义的8×8点阵图样式。每个字节的8个二进制表示水平8点,8字节表示8行,然后以此模型向整个封闭区域填充。例、用setfillpattern()函数设置用户自定义的填图模式。char upattern[8]={0x00,0x24,0x7e,0x3c,0x3c,0x7e,0x24,0x00};#include”graphics.h“ main(){ int i,gdriver=DETECT,gmode;initgraph(&gdriver,&gmode,”d: urboc2");setfillpattern(upattern,RED);setcolor(YELLOW);circle(200,200,100);floodfill(200,200,YELLOW);
/*pattern.c*/ getch();closegraph();}
五、图形方式下的文本
1、设置正文字形、显示方向、字符大小函数
void far settextstyle(font, direction, charsize)int font, direction, charsize;font(字形)取值,0:8*8字形,1:3倍笔划字形,2:小号笔划字形,3:无衬线笔划字形,4:黑体笔划字形。
direction(显示方向)取值,0:自左向右,1:由底向上。charsize(字符放大因子)取值,0:用户自定义,1:8*8大小,2:16*16大小,„„。最大为10倍。说明:该函数影响outtext()和outtextxy()两个函数。
2、用当前对齐方式、字形、方向、大小在屏幕上(x,y)显示字符串函数
6/7
计算机图形学第二章 Turbo C的图形功能
void far outtextxy(x, y, textstring)
int x, y;
char *textstring;(为字符串指针,不能是汉字)
3、用当前对齐方式、字形、方向、大小在屏幕上当前位置(cp)显示字符串函数
void far outtext(textstring)char *textstring;(为字符串指针,不能是汉字)
六、字符屏幕控制函数
(包含在conio.h头文件中)
1、清除屏幕并将光标移到左上角函数
void clrscr(void)
2、设置背景颜色函数
void textbackground(int color)
3、设置前景字符颜色函数
void textcolor(int color)
4、将光标移到指定位置函数
void gotoxy(int x, int y)
5、获得光标位置函数
(1)int wherex(void),(2)int wherey(void)
6、向屏幕写字符函数
printf(“%s%c”,变量表),puts(字符串)
7/7
第三篇:图形学实验5
《3D游戏图形学》
实验报告书
(实验五)
姓名:
学号: 班级:
浙江理工大学 二0一二 年 十二 月
数字图像处理实验指导书
实验五 纹理映射实验
一、实验目的和要求
掌握纹理映射的基本原理,利用VC++ OpenGL实现纹理映射技术。
二、实验原理
纹理映射是真实感图形制作的一个重要部分,运用纹理映射可以方面地制作真实感图形,而不必花更多的时间去考虑物体的表面纹理。如一张木制桌子其表面的木纹是不规范的,看上去又是那么自然,如果在图形制作中不用纹理映射,那么只是这张桌面纹理的设计,就要花费很大精力,而且设计结果也未必能像现实中那么自然。如果运用纹理映射就非常方便,可以用扫描仪将这样的一张桌子扫成一个位图。然后的具体的操作中,只需把桌面形状用多边形画出来,把桌面纹理贴上去就可以了。
另外,纹理映射能够在多边形进行变换时仍保证纹理的图案与多边形保持一致性。例如,以透视投影方式观察墙面时,远端的砖会变小,而近处的砖就会大一些。
此外,纹理映射也可以用于其他方面。例如,使用一大片植被的图像映射到一些连续的多边形上,以模拟地貌,或者以大理石、木纹等自然物质的图像作为纹理映射到相应的多边形上,作为物体的真实表面。
在OpenGL中提供了一系列完整的纹理操作函数,用户可以用它们构造理想的物体表面,可以对光照物体进行处理,使其映射出所处环境的景象,可以用不同方式应用到曲面上,而且可以随几何物体的几何属性变换而变化,从而使制作的三维场景和三维物体更真实更自然。
在OpenGL中要实现纹理映射,需要经历创建纹理、指定纹理应用方式、启用纹理映射、使用纹理坐标和几何坐标绘制场景几个过程。
用于指定一维、二维和三维纹理的函数分别为: Void glTexImage1D(GLenum target, Glint level, Glint components, GLsizei width, Glint border, GLenum format, GLenum type, const GLvoid *texels);Void glTexImage2D(GLenum target, Glint level, Glint components, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *texels);Void glTexImage3D(GLenum target, Glint level, Glint components, GLsizei width, GLsizei height, GLsizei depth, Glint border, GLenum format, GLenum type, const GLvoid *texels);其中,参数target取值一般为GL_TEXTURE_1D, GL_TEXTURE_2D和GL_TEXTURE_3D,分别与一维、二维和三维的纹理相对应。参数Level表示纹理多分辨率层数,通常取值为0,表示只有一种分辨率。参数components的可能取值为1~4的整数以及多种符号常量(如GL_RGBA),表示纹理元素中存储的哪些分量(RGBA颜色、深度等)在纹理映射中被使用,1表示使用R颜色分量,2表示使用R和A颜色分量,3表示使用RGB颜色分量,4表示使用RGBA颜色分量。参数width,height,depth分别指定纹理的宽度、高度、深度。参数format和type表示给出的图像数据的数据格式和数据类型,这两个参数的取值都是符号常量(比如format指定为GL_RGBA,type指定为GL_UNSIGNED_BYTE,参数texels指向内存中指定的纹理图像数据。
在定义了纹理之后,需要启用纹理的函数: 数字图像处理实验指导书
glEnable(GL_TEXTURE_1D);glEnable(GL_TEXTURE_2D);glEnable(GL_TEXTURE_3D);在启用纹理之后,需要建立物体表面上点与纹理空间的对应关系,即在绘制基本图元时,在glVertex函数调用之前调用glTexCoord函数,明确指定当前顶点所对应的纹理坐标,例如:
glBegin(GL_TRIANGLES);glTexCoord2f(0.0, 0.0);glVertex2f(0.0, 0.0);glTexCoord2f(1.0, 1.0);glVertex2f(15.0, 15.0);glTexCoord2f(1.0, 0.0);glVertex2f(30.0, 0.0);glEnd();其图元内部点的纹理坐标利用顶点处的纹理坐标采用线性插值的方法计算出来。
在OpenGL中,纹理坐标的范围被指定在[0,1]之间,而在使用映射函数进行纹理坐标计算时,有可能得到不在[0,1]之间的坐标。此时OpenGL有两种处理方式,一种是截断,另一种是重复,它们被称为环绕模式。在截断模式(GL_CLAMP)中,将大于1.0的纹理坐标设置为1.0,将小于0.0的纹理坐标设置为0.0。在重复模式(GL_REPEAT)中,如果纹理坐标不在[0,1]之间,则将纹理坐标值的整数部分舍弃,只使用小数部分,这样使纹理图像在物体表面重复出现。例如,使用下面的函数:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);分别指定二维纹理中s坐标采用截断或重复处理方式。
另外,在变换和纹理映射后,屏幕上的一个像素可能对应纹理元素的一小部分(放大),也可能对应大量的处理元素(缩小)。在OpenGL中,允许指定多种方式来决定如何完成像素与纹理元素对应的计算方法(滤波)。比如,下面的函数可以指定放大和缩小的滤波方法:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);其中,glTexParameteri函数的第一个参数指定使用的是一维、二维或三维纹理;第二个参数为GL_TEXTURE_MAG_FILTER或GL_TEXTURE_MIN_FILTER,指出要指定缩小还是放大滤波算法;最后一个参数指定滤波的方法。
补充:透视投影函数
void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);它也创建一个对称透视视景体,但它的参数定义于前面的不同。其操作是创建一个对称的透视投影矩阵,并且用这个矩阵乘以当前矩阵。参数fovy定义视野在X-Z平面的角度,范围是[0.0,180.0];参数aspect是投影平面宽度与高度的比率;参数zNear和Far分别是远近裁剪面沿Z负轴到视点的距离,它们总为正值。
三、实验内容
在OpenGL中纹理映射所使用的纹理数据,既可以是程序生成的一组数据,也可以从外部文件中直接读取,参考示范代码完成以下两项内容: 1.利用直接创建纹理的方法生成二维纹理并映射到四边形上。参考代码:
void makeImage(void){ 数字图像处理实验指导书
int i, j, r,g,b;for(i = 0;i < ImageWidth;i++){
for(j = 0;j < ImageHeight;j++)
{
r=(i*j)%255;
g=(4*i)%255;
b=(4*j)%255;
Image[i][j][0] =(GLubyte)r;
Image[i][j][1] =(GLubyte)g;
Image[i][j][2] =(GLubyte)b;
} }} void myinit(void){ glClearColor(0.0, 0.0, 0.0, 0.0);glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);// 生成纹理数据 makeImage();// 设置像素存储模式
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);// 定义二维纹理映射 glTexImage2D(……);// 定义纹理映射参数 glTexParameterf(……);glTexParameterf(……);glTexParameterf(……);glTexParameterf(……);// 启用二维纹理
glEnable(GL_TEXTURE_2D);glShadeModel(GL_FLAT);} void display(void){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//绘制四边形,并完成纹理映射
……
glFlush();} void myReshape(GLsizei w, GLsizei h){ ……} void main(int argc, char* argv[]){ ……} 2.从外部文件中直接读取纹理实现正方体每个面的纹理映射,并使正方体转动。
数字图像处理实验指导书
整个过程需要三个步骤:创建纹理、启用纹理映射和使用纹理坐标和几何坐标绘制,下面我们对三个过程进行阐述,并给出参考代码。1)创建纹理对象并绑定纹理
纹理创建即在内存中创建保存纹理数据的数组,一般是先读入一个图像文件,将图像文件的RGBA信息存入我们创建的纹理空间中,当然图像的位图不同,创建的纹理空间结构也会有所不同。为了更加简单易懂地实现这个过程,我们使用未压缩的纹理。代码:
GLuinttexture[1];//创建一个纹理空间
AUX_RGBImageRec *LoadBMP(CHAR *Filename)//载入位图图像 { FILE *File=NULL;//文件句柄
if(!Filename)//确保文件名已提供
{
return NULL;} File=fopen(Filename, “r”);//尝试打开文件
if(File){
fclose(File);//关闭文件
return auxDIBImageLoadA(Filename);//载入位图并返回指针
} return NULL;} //如果载入失败,返回NULL int LoadGLTextures()//载入位图并转换成纹理 { int Status=FALSE;//状态指示器
AUX_RGBImageRec *TextureImage[1];//创建纹理的存储空间
memset(TextureImage, 0, sizeof(void *)*1);//初始化 //载入位图,检查有无错误,如果位图没找到则退出
if(TextureImage[0]=LoadBMP(“data.bmp”)){
Status=TRUE;
glGenTextures(1,&texture[0]);//创建纹理 //使用来自位图数据生成的典型纹理
glBindTexture(GL_TEXTURE_2D, texture[0]);//生成2D纹理
glTexImage2D(GL_TEXTURE_2D,0,3,TextureImage[0]->sizeX,TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);} if(TextureImage[0])//纹理是否存在{
if(TextureImage[0]->data)//纹理图像是否存在 { 数字图像处理实验指导书
free(TextureImage[0]->data);//释放纹理图像占用的内存
}
free(TextureImage[0]);//释放图像结构
} return Status;//返回Status }
2)启用纹理映射操作,初始化相关参数
在OpenGL中使用纹理映射之前,必须打开纹理映射。int InitGL(GLvoid){ if(!LoadGLTextures())//调用纹理载入子例程
{
return FALSE;} glEnable(GL_TEXTURE_2D);//启用纹理映射
glShadeModel(GL_SMOOTH);//启用阴影平滑
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);//黑色背景
glClearDepth(1.0f);//设置深度缓存
glEnable(GL_DEPTH_TEST);//启用深度测试
return TRUE;}
3)使用纹理坐标和几何坐标绘制 void DrawGLScene(void){ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glLoadIdentity();glTranslatef(0.0f,0.0f,-5.0f);glRotatef(xrot,1.0f,0.0f,0.0f);glRotatef(yrot,0.0f,1.0f,0.0f);glRotatef(zrot,0.0f,0.0f,1.0f);// 选择纹理
glBindTexture(GL_TEXTURE_2D,texture[0]);//绘制一个正方体,给每个面贴上纹理,并使之转动
glBegin(GL_QUADS);……
glEnd();xrot+=0.3f;yrot+=0.2f;zrot+=0.4f;}
四、实验代码 数字图像处理实验指导书
1、利用直接创建纹理的方法生成二维纹理并映射到四边形上。#include
#define imageWidth 64 #define imageHeight 64 GLubyte image[imageWidth][imageHeight][3];
/*绘制一个简单的二维纹理图*/ void makeImage(void){ int i,j,r,g,b;
/*根据点的位置设置不同的颜色*/ for(i = 0;i < imageWidth;i++){
for(j = 0;j r =(i*j)%255; g =(i*i)%255; b =(j*j)%255; image[i][j][0] =(GLubyte)r; image[i][j][1] =(GLubyte)g; image[i][j][2] =(GLubyte)b; } } } void myInit(void){ glClearColor(0.0,0.0,0.0,0.0);glEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);// 生成纹理数据 makeImage();// 设置像素存储模式 glPixelStorei(GL_UNPACK_ALIGNMENT,1);/*指定二维纹理映射*/ glTexImage2D(GL_TEXTURE_2D,0,3,imageWidth,imageHeight,0,GL_RGB,GL_UNSIGNED_BYTE,&image[0][0][0]);//纹理过滤函数 /*GL_TEXTURE_2D: 操作D纹理.GL_TEXTURE_WRAP_S: S方向上的贴图模式.GL_CLAMP: 将纹理坐标限制在.0,1.0的范围之内.如果超出了会如何呢.不会错误,只是会边缘拉伸填充.GL_TEXTURE_MAG_FILTER: 放大过滤 GL_LINEAR: 线性过滤, 使用距离当前渲染像素中心最近的个纹素加权平均值.数字图像处理实验指导书 GL_TEXTURE_MIN_FILTER: 缩小过滤 GL_LINEAR_MIPMAP_NEAREST: 使用GL_NEAREST对最接近当前多边形的解析度的两个层级贴图进行采样,然后用这两个值进行线性插值.*/ glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);/*设置纹理环境参数*/ //glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);// 启用二维纹理 glEnable(GL_TEXTURE_2D);glShadeModel(GL_FLAT);} void myDisplay(void){ glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);/*将纹理映射到四边形上*/ glBegin(GL_QUADS);/*纹理的坐标和四边形顶点的对应*/ glTexCoord2f(0.0,0.0);glVertex3f(-0.7,-0.25,0.0);glTexCoord2f(0.0,1.0);glVertex3f(-0.2,-0.25,0.0);glTexCoord2f(1.0,1.0);glVertex3f(-0.2,0.25,0.0);glTexCoord2f(1.0,0.0);glVertex3f(-0.7,0.25,0.0);glTexCoord2f(0.0,0.0);glVertex3f(0.2,-0.25,1.875);glTexCoord2f(0.0,1.0);glVertex3f(0.6,-0.25,0.0);glTexCoord2f(1.0,1.0);glVertex3f(0.6,0.25,0.125);glTexCoord2f(1.0,0.0);glVertex3f(0.2,0.25,2.0);glEnd();glFlush();} void myReshape(int w,int h){ glViewport(0,0,(GLsizei)w,(GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(80.0,1.0-(GLfloat)w/(GLfloat)h,1.0,30.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();} int main(int argc,char **argv){ /*初始化*/ glutInit(&argc,argv);glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);glutInitWindowSize(400,400);数字图像处理实验指导书 glutInitWindowPosition(200,200);glutCreateWindow(“ Texture ”);//创建窗口 myInit();//绘制与显示 glutReshapeFunc(myReshape);glutDisplayFunc(myDisplay);glutMainLoop();return 0;} 2、从外部文件中直接读取纹理实现正方体每个面的纹理映射,并使正方体转动。#include #include #include #include #include #pragma comment(lib, “openGL32.lib”)#pragma comment(lib, “glu32.lib”)#pragma comment(lib, “glaux.lib”)#pragma comment(lib,“openGL32.lib”)GLuint texture[1];//创建纹理空间 GLfloat xRot,yRot,zRot;//控制正方体的旋转 //载入位图图像 AUX_RGBImageRec *LoadBMP(CHAR *Filename){ //载入位图图像 FILE *File=NULL; //文件句柄 if(!Filename){ //确保文件名已提供 return NULL;} File=fopen(Filename, “r”); //尝试打开文件 if(File){ fclose(File); //关闭文件 return auxDIBImageLoadA(Filename); //载入位图并返回指针 } return NULL; //如果载入失败,返回NULL } int LoadGLTextures(){ //载入位图并转换成纹理 int Status=FALSE; //状态指示器 AUX_RGBImageRec *TextureImage[1]; //创建纹理的存储空间 memset(TextureImage, 0, sizeof(void *)*1);//初始化 //载入位图,检查有无错误,如果位图没找到则退出 if(TextureImage[0]=LoadBMP(“data.bmp”)){ Status=TRUE; glGenTextures(1,&texture[0]); //创建纹理 //使用来自位图数据生成的典型纹理 glBindTexture(GL_TEXTURE_2D, texture[0]); //生成D纹理 数字图像处理实验指导书 glTexImage2D(GL_TEXTURE_2D,0,3,TextureImage[0]->sizeX,TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);} if(TextureImage[0]){ //纹理是否存在if(TextureImage[0]->data){ //纹理图像是否存在free(TextureImage[0]->data); //释放纹理图像占用的内存 } free(TextureImage[0]); //释放图像结构 } return Status; //返回Status } int InitGL(GLvoid){ if(!LoadGLTextures()){ //调用纹理载入子例程 return FALSE;} glEnable(GL_TEXTURE_2D); //启用纹理映射 glShadeModel(GL_SMOOTH); //启用阴影平滑 glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //黑色背景 glClearDepth(1.0f); //设置深度缓存 glEnable(GL_DEPTH_TEST); //启用深度测试 return TRUE;} void display(){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0f,0.0f,-5.0f); glRotatef(xRot,1.0f,0.0f,0.0f); glRotatef(yRot,0.0f,1.0f,0.0f); glRotatef(zRot,0.0f,0.0f,1.0f); //绘制正方体,贴上纹理并使之转动 glBindTexture(GL_TEXTURE_2D,texture[0]);//选择纹理 glBegin(GL_QUADS); //前 glTexCoord2f(0.0f, 0.0f);glVertex3f(-1.0f,-1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f);glVertex3f(1.0f,-1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f);glVertex3f(1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f);glVertex3f(-1.0f, 1.0f, 1.0f); glEnd(); glBindTexture(GL_TEXTURE_2D,texture[0]); glBegin(GL_QUADS); //后 glTexCoord2f(1.0f, 0.0f);glVertex3f(-1.0f,-1.0f,-1.0f);数字图像处理实验指导书 glTexCoord2f(1.0f, 1.0f);glVertex3f(-1.0f, 1.0f,-1.0f); glTexCoord2f(0.0f, 1.0f);glVertex3f(1.0f, 1.0f,-1.0f); glTexCoord2f(0.0f, 0.0f);glVertex3f(1.0f,-1.0f,-1.0f); glEnd(); glBindTexture(GL_TEXTURE_2D,texture[0]); glBegin(GL_QUADS); // 上 glTexCoord2f(0.0f, 1.0f);glVertex3f(-1.0f, 1.0f,-1.0f); glTexCoord2f(0.0f, 0.0f);glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f);glVertex3f(1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f);glVertex3f(1.0f, 1.0f,-1.0f); glEnd(); glBindTexture(GL_TEXTURE_2D,texture[0]); glBegin(GL_QUADS); //下 glTexCoord2f(1.0f, 1.0f);glVertex3f(-1.0f,-1.0f,-1.0f); glTexCoord2f(0.0f, 1.0f);glVertex3f(1.0f,-1.0f,-1.0f); glTexCoord2f(0.0f, 0.0f);glVertex3f(1.0f,-1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f);glVertex3f(-1.0f,-1.0f, 1.0f); glEnd(); glBindTexture(GL_TEXTURE_2D,texture[0]); glBegin(GL_QUADS); //右 glTexCoord2f(1.0f, 0.0f);glVertex3f(1.0f,-1.0f,-1.0f); glTexCoord2f(1.0f, 1.0f);glVertex3f(1.0f, 1.0f,-1.0f); glTexCoord2f(0.0f, 1.0f);glVertex3f(1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f);glVertex3f(1.0f,-1.0f, 1.0f); glEnd(); glBindTexture(GL_TEXTURE_2D,texture[0]); glBegin(GL_QUADS); //左 glTexCoord2f(0.0f, 0.0f);glVertex3f(-1.0f,-1.0f,-1.0f); glTexCoord2f(1.0f, 0.0f);glVertex3f(-1.0f,-1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f);glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f);glVertex3f(-1.0f, 1.0f,-1.0f); glEnd(); glutPostRedisplay(); glutSwapBuffers(); } void reshape(int w,int h){ if(0 == h) h = 1; glViewport(0,0,(GLsizei)w,(GLsizei)h); glMatrixMode(GL_PROJECTION);数字图像处理实验指导书 glLoadIdentity(); gluPerspective(60.0f,(GLfloat)w /(GLfloat)h,1,100); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } void spinDisplay(void){ xRot += 0.2f; yRot += 0.2f; glutPostRedisplay();} void mouse(int button, int state, int x, int y)//鼠标监听 { switch(button){ case GLUT_LEFT_BUTTON: if(state == GLUT_DOWN) glutIdleFunc(spinDisplay);//设备空闲时调用的函数 break; case GLUT_MIDDLE_BUTTON: case GLUT_RIGHT_BUTTON: if(state == GLUT_DOWN) glutIdleFunc(NULL); break; default: break; } } int main(int argc,char** argv){ glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(400,400); glutInitWindowPosition(100,100); glutCreateWindow(“Texture Map”); InitGL(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMouseFunc(mouse);//鼠标监听 glutMainLoop(); return 0; } 五、实验结果 1、利用直接创建纹理的方法生成二维纹理并映射到四边形上。数字图像处理实验指导书 2、从外部文件中直接读取纹理实现正方体每个面的纹理映射,并使正方体转动。(按左键转动,按右键停止) 六、实验心得 《计算机图形学》学习报告 东西方建筑中的理性 尽管东方“木构”的暂时性文化和西方“石砌”的永久性文化氛围造成了建筑形式风格的差异,但是它们都兼有理性和感性美。从柱式的英文“order”一词,到中国古建筑等级制的基数开间,无不透露着匠人的理性思考;从古埃及绘画中为了将人的特征最大限度表现而作的头部侧面身体正面的绘画,到文艺复兴达芬奇创造的透视画法,一步步将人们引向更为理性的世界。 西方古典主义者强调构图中的主从关系,突出轴线、讲求配称;倡导理性,主张建筑的真实,反对表现感情和情绪。随之而来的比例、节奏、韵律、秩序美,是建筑区别于雕塑和绘画两大艺术的特点。 维特鲁威提出的建筑三原则:坚固、适用、美观,时时刻刻提醒着我们建筑是要被建造起来的,它是我们的“避难所”,需要理性的结构、缜密的分析和思考。时代在进步,建筑理论从勒杜克的结构理性主义发展到现在的解构主义,再也不是建筑形式适应结构的时代了,而是两者互为促进。 我们对建筑的理解不再是像路易斯康那样再去问砖想做什么,等待它做拱卷的回答。我们向大自然学习,卡拉特拉瓦创造了许多带有理性美的仿生建筑。当我们想进一步拓宽我们的思维时,我们还能向谁求助?计算机图形学为我们打开了理性思考的一扇窗。 计算机图形学对理性建筑的贡献 半个多世纪以来,计算机技术得到了飞速的发展。它的进步不仅仅使世界变得更平,信息交流更便捷,在此平台上开发的各种绘图软件更是将建筑师从传统的手工渲染画图中解放出来,也解放了结构师的工作量。用了30年的时间,计算机的速度从K(103)到T(1012),而从T到Z(1021),我们只用了10年时间。发展的速度是越来越快,我们设计方法和速度都得到了革新。这是这样一个数字化信息化的时代,才有弗兰克盖里建筑的夸张和扎哈哈迪德设计的新奇。 原来我们随手绘出的自由曲线,现在计算机都能帮我们算出是否有建造的可能,以及建筑性能也能在建造前得到分析。在创意上,计算机也能将我们模糊的概念无限发展,给它一个规则,它可能还你一个超乎想象的造型,在理性规则中生成感性而自由的建筑。 知其然,还应知其所以然,看着电视机的变薄,图像更加逼真,这变化的一切都建立在计算机图形学的架构下,了解了基础原理,才能更高效地做高质量的建筑设计。 计算机图形学的理论知识 1.相关概念 计算机图形学是主要研究通过计算机处理用集合数据和数学模型所描述的图形的原理、算法和系统。包括图形的输入、存储、运算、转换、传送和输出。数字化技术是泛指在某特定领域利用包括硬件、软件在内的计算机与电子技术以及数学或数字模型等描述的问题进行求解、模拟或分析活动的一切应用技术。 建筑数字化技术研究应用包括建筑的数字化设计和反映建筑的数字化特征在内的数字技术。而建筑数字化技术的核心几何学科就是计算机图形学。2.反映建筑数字化特征的典型图形技术 建筑的动态特征——图形显示:如奥地利格拉茨美术馆的925盏灯形成的外墙面显示屏 建筑的互动特征——图形显示:如杜瑟赫姆市的随情感变化而色彩变化的建筑物 建筑的数字特征——几何运算:如柏林Max Reinhardt大楼模型及“莫比乌斯环”变换 建筑的虚实特征——交互式图形:如法国国立图书馆(实体与网络图书馆) 设计手段和设计媒体的数字化特征——交互式图形:如纽约韩国基督教长老会教堂 而建筑性能如声环境、热环境、光环境、风环境模拟的可视化分析中都用到了图形学。3.虚拟现实技术(VR) 虚拟现实技术是计算机生成的给人多种感官刺激的虚拟世界(环境),是一种高级的人机交互系统。 虚拟现实技术的三个基本特征:沉浸感、交互性、想象力 它具有多学科的综合性,正如建筑学是一门综合的艺术,虚拟现实技术包括图像处理、图形学、计算几何、多传感器、网络、多媒体和仿真技术等。 正如课堂上老师放映的《碟中谍4》,逼真的爆炸场景,以及从皮克斯动画开始的动物毛发到最近火热的《少年派》逼真的老虎与人共存画面,虚拟现实技术的进步影响到了我们生活的方方面面,触到了我们原来想都不敢想的世界。 而VR技术在建筑行业中,有以下作用:(1)指导设计:让建筑师通过浏览观察和了解空间关系,特别是对空间大小、方向、形状和建筑元素行为的理解。(2)建筑表现与环境仿真(3)仿真施工:检查和修改施工细节、合理性和有效性 4.虚拟现实的基础与关键技术:建模与描绘 基于几何和图形学的建模和描绘技术 直接几何建模 3D扫描建模 投影视图建模 基于图像的场景描绘技术(IBR) 图像投影变形技术 光场重建技术 混合式IBR技术 IBR技术图形的绘制独立于场景的复杂性,仅仅与所要生成画面的分辨率有关。 实验三 MFC画直线 最近自己在学习如何在VC 6.0 开发环境下的使用MFC AppWizard(exe)来绘画一条直线,虽然比较简单,通过这样的练习可以帮助你熟悉MFC的开发环境以及其中的消息传递机制,希望对于像我一样初入MFC图形绘制学习的人有帮 助 第一步:构建MFC窗体 打开Visual C++ 6.0编译器 新建→工程→MFC AppWizard(exe),工程名以DrawLine为例,然后确定。为了方便,在MFC应用程序向导—步骤1当中选择“单文档”,其余所有的步骤都为默认值,直接“完成”。这样一个简单的MFC窗体就构建好了,自己不妨Compile—Build—BuildExecute一下。 第二步:编辑菜单项 选择ResourceView视窗展开Menu文件夹,左键双击IDR_DRAWLITYPE,右边就会出现菜单图形编辑界面,为了简化,我们只在添加帮助→DrawLine功能选择项。双击空白会弹出“菜单项目 属性”对话框。ID:ID_DRAW_LINE;标明: DrawLine(&D),其它的为缺省。 第三步:建立消息命令 如果此时运行该程序,你会发现帮助—DrawLine的功能选项是灰色的,原因就在于我们还没有添加该功能的消息命令相应函数。通过“查看—Message Maps—Project:DrawLine—Class name:CDrawLineView—Object IDs:ID_DRAW_LINE—选定COMMAND—Add Function„”,其它为默认,最后确定完成。现在如果再重新运行该程序的话,会发现原来的灰色已经消除了。 第四步:添加鼠标消息响应 打开ClassView视窗,右键选定CDrawLineView,选择Add Windows Messsage Handler会弹出对话框,完成CDrawLineView类的WM_LBUTTONDOWN、WM_MOUSEMOVE、WM_LBUTTONUP三个Windows消息事件的新建。 第五步:添加响应代码 首先,在ClassView视窗中双击CDrawLineView会定位到“DrawLineView.h : interface of the CDrawLineView class”的文件,添加CDrawLineView类的成员:protected: int m_Drag;POINT m_pPrev;POINT m_pOrigin;三个成员变量。视窗中展开CDrawLineView类,双击定位OnLBUTTONDOWN()函数。在该函数消息响应 处添加如下代码: //建立好绘图的设备环境 CClientDC dc(this);OnPrepareDC(&dc); dc.DPtoLP(&point); //获取起始点坐标 m_pPrev=point;m_pOrigin=point; m_Drag=1; 然后,定位于OnMouseMove(),添加如下代码(其中关键用到了橡皮筋技术): //建立好绘图的设备环境 CClientDC dc(this); OnPrepareDC(&dc);dc.DPtoLP(&point); dc.SetROP2(R2_NOT);//橡皮筋绘图技术 //判断是否BUTTONDOWN if(m_Drag) { dc.MoveTo(m_pOrigin);dc.LineTo(m_pPrev);dc.MoveTo(m_pOrigin);dc.LineTo(point); } m_pPrev=point; 最后,在OnLBUTTONDOWN()添加代码: m_Drag=0; 程序运行效果图 实验4 实现圆的生成算法 一、实验目的 1.熟悉CDC图形程序库; 2.掌握中点画圆生成算法; 3.掌握Bresenham画圆算法。 二、实验内容 利用VisualC++6.0设计一个简易画圆绘图板,验证圆生成算法。 三、实验指导 1.生成绘图应用程序的框架,如下图所示。具体实现见第二次实验,过程不再详细说明。 2.在应用程序中增加菜单 完成相关菜单的设计,具体的效果如下图所示,并设置好相关菜单消息的映射,具体的实现在前面的实验中介绍过,再此不在详细说明。 3.在绘图函数中添加代码 通过以上步骤,得到了与菜单对应的消息映射,就可以在函数中添加代码绘制图形了。(1)利用中点画圆算法实现圆的生成(算法原理见教材)。void CDraw_CirView::OnMid(){ // TODO: Add your command handler code here CDC*pDC=GetDC();//得到绘图类指针 RedrawWindow();//重绘窗口 int x,y,x0=200,y0=200,r=100;//圆的圆心为(x0,y0),半径为r float d;x=0;y=r;d=1.25-r; pDC->SetPixel(x+x0,y+y0,RGB(255,0,0));pDC->SetPixel(y+x0,x+y0,RGB(255,0,0));pDC->SetPixel(y+x0,-x+y0,RGB(255,0,0));pDC->SetPixel(x+x0,-y+y0,RGB(255,0,0));pDC->SetPixel(-x+x0,-y+y0,RGB(255,0,0));pDC->SetPixel(-y+x0,-x+y0,RGB(255,0,0));pDC->SetPixel(-y+x0,x+y0,RGB(255,0,0));pDC->SetPixel(-x+x0,y+y0,RGB(255,0,0));while(x<=y){ if(d<0) { d=d+2*x+3; x++; } else { d=d+2*(x-y)+5; x++; y--;} pDC->SetPixel(x+x0,y+y0,RGB(255,0,0)); pDC->SetPixel(y+x0,x+y0,RGB(255,0,0)); pDC->SetPixel(y+x0,-x+y0,RGB(255,0,0)); pDC->SetPixel(x+x0,-y+y0,RGB(255,0,0)); pDC->SetPixel(-x+x0,-y+y0,RGB(255,0,0)); pDC->SetPixel(-y+x0,-x+y0,RGB(255,0,0)); pDC->SetPixel(-y+x0,x+y0,RGB(255,0,0)); pDC->SetPixel(-x+x0,y+y0,RGB(255,0,0));} } 由以上代码绘出的图形如下: (2)利用Bresenham算法生成圆(算法原理见教材)。void CDraw_CirView::OnBre(){ // TODO: Add your command handler code here CDC*pDC=GetDC();//得到绘图类指针 //RedrawWindow();//重绘窗口 int x,y,x0=200,y0=200,r=50;//圆的圆心为(x0,y0),半径为r int delta,delta1,delta2,direction;x=0;y=r;delta=2*(1-r);while(y>=0){ pDC->SetPixel(x+x0,y+y0,RGB(0,0,255)); pDC->SetPixel(x+x0,-y+y0,RGB(0,0,255)); pDC->SetPixel(-x+x0,y+y0,RGB(0,0,255)); pDC->SetPixel(-x+x0,-y+y0,RGB(0,0,255)); if(delta<0) { delta1=2*(delta+y)-1; if(delta<=0)direction=1; else direction=2; } else if(delta>0) { delta2=2*(delta-x)-1; if(delta2<=0)direction=2; else direction=3; } else direction=2; switch(direction) { case 1:x++; delta+=2*x+1; break; case 2:x++;y--; delta+=2*(x-y+1); break; case 3:y--; delta+=(-2*y+1); break; } } } 由以上代码绘出的图形如下: (3)以上是本次实验的基本部分,利用中点画圆和Bresenham画圆算法实现的基本图形的绘制。能不能利用该算法,完成一些复杂图形的生成,比如利用基本的画圆算法绘制一个奥运五环。甚至根据画圆算法,实现二次曲线的生成,如椭圆的生成等等。请同学们认真考虑,完成这部分的内容,上机调试。 四、思考 1.如何实现圆心为任意位置的圆的绘制; 2.两种画圆算法的比较。第四篇:计算机图形学学习心得
第五篇:计算机图形学实验