山东科技大学计算机图形学实验指导书.docx
《山东科技大学计算机图形学实验指导书.docx》由会员分享,可在线阅读,更多相关《山东科技大学计算机图形学实验指导书.docx(33页珍藏版)》请在冰豆网上搜索。
山东科技大学计算机图形学实验指导书
计算机图形学
实验指导书
张晓庆
信息科学与工程学院
2010年5月
目录
实验一环境设置(2学时)
实验二直线和圆的生成算法(2学时)
实验三填充和裁剪算法(4学时)
实验四(选择1)二维图形的几何变换(2学时)
实验四(选择2)真实感图形的绘制(2学时)
实验一环境设置(2学时)
一、实验目的
1.掌握图形驱动程序及图形模式的基本概念,掌握图形初始化方法;
2.掌握TurboC进行图形程序设计的基本方法;
3.了解TurboC的图形功能,了解常见的图形库函数;
4.初步了解OpenGL程序设计结构;了解OpenGL的基本数据类型、核心函数及辅助函数的使用。
二、实验要求
1.图形系统初始化;
2.综合应用TurboC中图形库函数,进行图形设计与绘制;
3.熟悉TurboC和OpenGL开发环境,要求会对程序进行编辑,编译,调试(包括分步,断点设置等调试手段)。
三、实验内容
1.图形系统初始化
#include
include
include
include
intmain(void)
{
intgdriver=DETECT,gmode=0;
initgraph(&gdiver,&gmode,”C:
\\BC31\\BGI”);//进行图形初始化,//图形卡的采用自动检//测模式,同时//假设BC系统安装在C盘的BC31子目//录下。
setcolor(4);//设定当前前景色为红色
circle(300,300,100);//以点(300,300)为圆心,100为半径画//圆周。
setcolor
(2);//设定当前前景色为绿色
line(100,100,100,600);//在点(100,100)和点(100,600)之间画一条//直线段,并和以下三句结合,画出长为//500宽为400的矩形。
line(100,500,500,500);
line(500,500,500,100);
line(500,100,100,100);
getch();//从键盘上获取一个字符,在此表示暂停,供//操作者观察图形。
closegrap();//关闭图形模式。
}
2.综合应用TurboC中图形库函数,进行图形设计与绘制
TurboC的库函数见附录A
3.这次试验的目的主要是使大家初步熟悉OpenGL这一图形系统的用法,编程平台是VisualC++,它对OpenGL提供了完备的支持。
OpenGL提供了一系列的辅助函数,用于简化Windows操作系统的窗口操作,使我们能把注意力集中到图形编程上,这次试验的程序就采用这些辅助函数。
(1)、在VC中新建项目
∙新建一个项目。
选择菜单File中的New选项,弹出一个分页的对话框,选中页Projects中的Win32ConsoleApplication项,然后填入你自己的Projectname,如Test,回车即可。
VC为你创建一个工作区(WorkSpace),你的项目Test就放在这个工作区里。
∙为项目添加文件
为了使用OpenGL,我们需要在项目中加入三个相关的Lib文件:
glu32.lib、glaux.lib、opengl32.lib,这三个文件位于c:
\programfiles\MicrosoftVisualStudio\vc98\lib目录中。
选中菜单Project->AddToProject->Files项(或用鼠标右键),把这三个文件加入项目,在FileView中会有显示。
这三个文件请务必加入,否则编译时会出错。
或者将这三个文件名添加到Project->Setting->Link->Object/libraryModules即可。
点击工具条中NewTextFile按钮,新建一个文本文件,存盘为Test.c作为你的源程序文件,再把它加入到项目中,然后就可以开始编程了。
#include
#include
#include
#include
//初始化OpenGL场景
voidmyinit(void)
{
glClearColor(0.0,0.0,0.0,0.0);//将背景置成黑色
glShadeModel(GL_FLAT);//设置明暗处理
}
//用户的绘图过程
voidCALLBACKdisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//清除缓存
glBegin(GL_LINES);//开始画一根白线
glColor3f(1.0f,1.0f,1.0f);
//设置颜色为白色
//设置第一根线的两个端点,请注意:
OpenGL坐标系的原点是在屏幕左下角
glVertex2f(10.0f,50.0f);
glVertex2f(110.0f,50.0f);
glColor3f(1.0f,0.0f,0.0f);
//设置颜色为红色
//设置第二根线的两个端点
glVertex2f(110.0f,50.0f);
glVertex2f(110.0f,150.0f);
glEnd();//画线结束
glFlush();//绘图结束
}
//
//主过程:
//初始化Windows的窗口界面
//并初始化OpenGL场景,绘图
intmain(intargc,char**argv)
{
auxInitDisplayMode(AUX_RGB);
//初始化显示模式,采用RGB彩色系统。
auxInitPosition(0,0,400,150);//初始化窗口位置、大小
auxInitWindow("DisplayLists");//初始化窗口,设置标题
myinit();
auxMainLoop(display);
//循环运行display过程,display由用户编写
return(0);
}
(2)、程序说明
每个函数的具体含义在程序注释中已作了叙述,不再多说。
OpenGL的函数在格式上很有特点,它以gl为前缀,并且函数名的最后一个字母指出所用的数据类型,如:
glColor3f(),字母f指明要使用浮点数。
字母前的数字指明参数个数或指明二维还是三维,如:
glVertex2f()是要设置二维的点。
OpenGL采用的是状态机的方式,用户设定一种状态,程序照此运行。
如:
glBegin(GL_LINES)设定画线状态(GL_LINES是OpenGL已定义好的常量),glColor3f()设定绘图所用颜色。
main()函数中的几个aux前缀函数是OpenGL提供的辅助库,用以初始化窗口,大家不必深究,我们关注的是display()函数,它是我们真正绘图的地方。
函数glColor3f()以RGB方式设置颜色,格式为:
glColor3f(red,green,blue),每种颜色值在(0.0,1.0)之间。
为了能显示更多的颜色,最好把系统设置成16位真彩色模式。
函数glVertex2f(x,y)设置二维顶点。
函数glBegin(UINTState)、glEnd()是最基本的作图函数,下面对它作一介绍。
如上所述,OpenGL是一个状态机,glBegin(UINTState)可以设定如下状态:
GL_POINTS画点
GL_LINES画线,每两个顶点(Vertex)为一组
GL_LINE_STRIP画线,把若干个顶点顺次连成折线
GL_LINE_LOOP画线,把若干个顶点顺次连成封闭折线
GL_TRIANGLES画三角形,每三个顶点为一组
GL_QUADS画四边形,每四个顶点为一组
GL_POLYGON画多边形
还有GL_TRIANGLE_STRIP,GL_TRIANGLE_FAN,GL_QUADS_STRIP等等。
大家可以把每一种状态都试一试。
程序可以有多组glBegin()、glEnd()并列的形式,如:
......
glBeing(GL_LINES);
......
glEnd();
glBeing(GL_QUADS);
......
glEnd();
......
除了上述的基本图元外,函数glRectf(x1,y1,x2,y2)可以画一个矩形,但这个函数不能放在glBegin()和glEnd()之间,下面的两句程序是画一个蓝色的矩形。
glColor3f(0.0f,0.0f,1.0f);
glRectf(10.0f,10.0f,50.0f,50.0f);
实验二直线和圆的生成算法(2学时)
一、实验目的
1.通过实现三种直线和圆生成算法对算法原理加深理解。
2.熟悉TurboC开发环境,要求会对程序进行编辑,编译,调试(包括分步,断点设置等调试手段)。
二、实验要求
在TurboC环境下实现三种直线生成算法。
三、实验内容
1)对逐点比较法、DDA算法、Bresenham算法进行理解。
2)画出程序流程图;
3)编写程序的源程序;
4)编辑源程序并进行调试;
5)进行特殊模式的运行测试,并结合情况进行调整;
6)打印源程序或把源程序以文件的形式提交。
四、实验报告
1)按实验报告册格式书写实验报告;
2)提交源程序文件或打印件。
五、建立工程步骤
1.在visualc++.net中使用opnengl,建立项目的步骤:
2、在visualc++中的建立控制台项目的步骤:
实验三填充和裁剪算法(4学时)
一、实验目的
1.加深对填充算法的理解。
2.综合运用以前学过数据结构和算法设计知识。
2.熟悉TurboC开发环境,要求会对程序进行编辑,编译,调试(包括分步,断点设置等调试手段)。
二、实验要求
在TurboC环境下实现扫描线种子填充算法和Y-X算法。
三、实验内容
1)对扫描线种子填充算法和Y-X算法、编码裁剪算法、中点分割裁剪算法进行复习理解进行复习理解。
2)画出程序流程图;
3)编写程序的源程序;
4)编辑源程序并进行调试;
5)打印源程序或把源程序以文件的形式提交。
四、实验报告
1)按实验报告册格式书写实验报告;
2)提交源程序文件或打印件。
五、建立win32应用程序工程。
1、visualc++ 6.0下的界面
接下来,请按实验二中的方法给上面建立的空项目添加文件“recursion.cpp”,由于同学们初次接触WIN32编程,所以对于下文中很多代码可暂时不要求理解,重点了解红色代码。
递归算法源码如下:
//INCLUDES///////////////////////////////////////////////
#defineWIN32_LEAN_AND_MEAN//justsaynotoMFC
#include//includeallthewindowsheaders
#include//includeusefulmacros
//DEFINES////////////////////////////////////////////////
//definesforwindows
#defineWINDOW_CLASS_NAME"WINCLASS1"
#defineWINDOW_WIDTH400
#defineWINDOW_HEIGHT300
//GLOBALS////////////////////////////////////////////////
HWNDmain_window_handle=NULL;//globallytrackmainwindow
HINSTANCEhinstance_app=NULL;//globallytrackhinstance
voidBoundaryFill4(HDC,int,int,COLORREF,COLORREF);
//FUNCTIONS//////////////////////////////////////////////
LRESULTCALLBACKWindowProc(HWNDhwnd,
UINTmessage,
WPARAMwParam,
LPARAMlParam)
{
//thisisthemainmessagehandlerofthesystem
HDChdc;//handletoadevicecontext
HPENhnewpen;
HPENholdpen;
//whatisthemessage
switch(message)
{
caseWM_RBUTTONDOWN:
hdc=GetDC(hwnd);
hnewpen=CreatePen(PS_SOLID,1,RGB(0,255,0));
holdpen=(HPEN)SelectObject(hdc,hnewpen);
//构造多边形
MoveToEx(hdc,30,40,NULL);
LineTo(hdc,60,40);
LineTo(hdc,90,100);
LineTo(hdc,60,150);
LineTo(hdc,30,150);
LineTo(hdc,30,40);
SelectObject(hdc,holdpen);
DeleteObject(hnewpen);
ReleaseDC(hwnd,hdc);
return(0);
break;
caseWM_LBUTTONDOWN:
hdc=GetDC(hwnd);BoundaryFill4(hdc,LOWORD(lParam),HIWORD(lParam),RGB(0,255,0),RGB(255,0,0));
//releasethedc
ReleaseDC(hwnd,hdc);
return(0);
break;
caseWM_DESTROY:
{
//killtheapplication,thissendsaWM_QUITmessage
PostQuitMessage(0);
//returnsuccess
return(0);
}break;
default:
break;
}//endswitch
//processanymessagesthatwedidn'ttakecareof
return(DefWindowProc(hwnd,message,wParam,lParam));
}//endWinProc
//WINMAIN////////////////////////////////////////////////
intWINAPIWinMain(HINSTANCEhinstance,
HINSTANCEhprevinstance,
LPSTRlpcmdline,
intncmdshow)
{
WNDCLASSEXwinclass;//thiswillholdtheclasswecreate
HWNDhwnd;//genericwindowhandle
MSGmessage;//genericmessage
//firstfillinthewindowclassstucture
winclass.cbSize=sizeof(WNDCLASSEX);
winclass.style=CS_DBLCLKS|CS_OWNDC|
CS_HREDRAW|CS_VREDRAW;
winclass.lpfnWndProc=WindowProc;
winclass.cbClsExtra=0;
winclass.cbWndExtra=0;
winclass.hInstance=hinstance;
winclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
winclass.hCursor=LoadCursor(NULL,IDC_ARROW);
winclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
winclass.lpszMenuName=NULL;
winclass.lpszClassName=WINDOW_CLASS_NAME;
winclass.hIconSm=LoadIcon(NULL,IDI_APPLICATION);
//savehinstanceinglobal
hinstance_app=hinstance;
//registerthewindowclass
if(!
RegisterClassEx(&winclass))
return(0);
//createthewindow
if(!
(hwnd=CreateWindowEx(NULL,//extendedstyle
WINDOW_CLASS_NAME,//class
"ScanlineFillDemo",//title
WS_OVERLAPPEDWINDOW|WS_VISIBLE,
0,0,//initialx,y
WINDOW_WIDTH,//initialwidth
WINDOW_HEIGHT,//initialheight
NULL,//handletoparent
NULL,//handletomenu
hinstance,//instanceofthisapplication
NULL)))//extracreationparms
return(0);
//savemainwindowhandle
main_window_handle=hwnd;
while(GetMessage(&message,NULL,0,0))
{
//translateanyacceleratorkeys
TranslateMessage(&message);
//sendthemessagetothewindowproc
DispatchMessage(&message);
}//endwhile
//returntoWindowslikethis
return(message.wParam);
}//endWinMain
///////////////////////////////////////////////////////////
voidBoundaryFill4(HDChdc,intx,inty,COLORREFboundarycolor,COLORREFnewcolor)
{
COLORREFcolor;
color=GetPixel(hdc,x,y);
if((color!
=boundarycolor)&&(color!
=newcolor))
{
SetPixel(hdc,x,y,newcolor);
BoundaryFill4(hdc,x,y+1,boundarycolor,newcolor);
BoundaryFill4(hdc,x,y-1,boundarycolor,newcolor);
BoundaryFill4(hdc,x-1,y,boundarycolor,newcolor);
BoundaryFill4(hdc,x+1,y,boundarycolor,newcolor);
}
}
2、中建立Win32工程
更改项目中recursion.cpp文件代码:
1)声明函数
voidBoundaryFill4(HDC,int,int,COLORREF,COLORREF);
2)修改LRESULTCALLBACKWndProc(HWNDhWnd,UINTmessage,WPARAMwParam,LPARAMlParam)函数中代码,把visualc++6.0介绍的recursion.cpp中的WndProc函数体复制即可。
3)在recursion.cpp文件末尾添加BoundaryFill4函数。
2.
下面的程序绘制的是一个简单的太阳系,其中包括一个太阳和一颗行星,它们使用线框球体绘制函数实现。
当按下键盘“D”或“d”时,行星将实现自转;按下键盘“Y”或“y”时,行星将绕太阳公转。
请同学们认真读懂每一段代码,然后试着修改这段程序,实现
1)将行星的中心倾斜;
2)给行星加上卫星。
#include
#include
staticintyear=0,day=0;
voidinit(void)
{
glClearColor(0.0,0.0,0.0,0.0);
glShadeModel(GL_FLAT);
}
voiddisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,1.0,1.0);
glPushMatrix();
//glutWireSphere中第一、二、三个参数分别表示半径,经度线数、纬度线数
glutWireSphere(1.0,20,16);/*drawsun*/
glRotatef((GLfloat)year,0.0,1.0,0.0);
glTranslatef(2.0,0.0,0.0);
glRotatef((GLfloat)day,0.0,1.0,0.0);
glutWireSphere(0.2,10,8);/*drawsmallerplanet*/
glPopMatrix();
glutSwapBuffers();
}
voidreshape(intw,inth)
{
glViewport(0,0,(GLsizei)w,(GLsizei)h);
gl