实验三 OpenGL的简单交互绘制new.docx
- 文档编号:7359595
- 上传时间:2023-01-23
- 格式:DOCX
- 页数:16
- 大小:74.91KB
实验三 OpenGL的简单交互绘制new.docx
《实验三 OpenGL的简单交互绘制new.docx》由会员分享,可在线阅读,更多相关《实验三 OpenGL的简单交互绘制new.docx(16页珍藏版)》请在冰豆网上搜索。
实验三OpenGL的简单交互绘制new
实验三OpenGL的简单交互绘制
一、实验目的
1、理解OpenGL坐标系的概念,掌握OpengGL裁剪窗口、视区、显示窗口的概念和它们之间的关系,学会计算世界坐标和屏幕坐标。
2、学会OpenGL的简单键盘交互操作。
3、学会OpenGL的简单字符绘制。
3、进一步掌握OpengGL点、直线、多边形的绘制。
二、实验环境
硬件要求:
PC机,主流配置,最好为独立显卡,显存512M以上。
软件环境:
操作系统:
WindowsXP。
语言开发工具:
MicrosoftVisualstudio2008,VisualC++。
程序框架:
Win32应用程序
三、实验内容与要求
3.1键盘交互
1、调出实验一的源代码运行,调整修改使得显示窗口在屏幕中央保持缺省大小(300*300),绘制的矩形在显示窗口中央。
如图2-1所示。
提示:
(1)添加修改窗口位置的函数glutInitWindowPosition(intx,inty);
其中(x,y)为窗口左上角在屏幕上的位置。
(2)显示窗口的左下角坐标为(-1,-1),右上角坐标为(1,1)。
图2-1
未修改前的win32初始源程序参考如下:
/*myfirstprogram.cpp*/
#include"stdafx.h"
#include
voiddisplay(void);
voidmyreshape(GLsizeiw,GLsizeih);
intAPIENTRY_tWinMain(HINSTANCEhInstance,
HINSTANCEhPrevInstance,
LPTSTRlpCmdLine,
intnCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
char*argv[]={"hello",""};
intargc=2;//must/shouldmatchthenumberofstringsinargv
glutInit(&argc,argv);//初始化GLUT库;
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);//设置显示模式;(缓冲,颜色类型)
glutInitWindowSize(500,500);
glutInitWindowPosition(1024/2-250,768/2-250);
glutCreateWindow("Hello");//创建窗口,标题为“hello”;
glutDisplayFunc(display);//用于绘制当前窗口;
glutMainLoop();//表示开始运行程序,用于程序的结尾;
return0;
}
voiddisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT);//刷新颜色缓冲区
glRectf(-0.5,-0.5,0.5,0.5);
glFlush();//用于刷新命令队列和缓冲区,使所有尚未被执行的OpenGL命令得到执行
}
2、在实验一的基础上添加键盘交互,按W键绘制的矩形上移,按S键矩形下移,按A键矩形左移,按D键矩形右移,如图2-2。
参考步骤如下:
(1)在主函数里添加注册键盘回调函数
glutKeyboardFunc(mykeyboard);
此函数可放在glutDisplayFunc(display);后面。
并在程序头部声明添加键盘回调函数:
voidmykeyboard(unsignedcharkey,intx,inty);
(2)在display()绘制函数中修改绘制矩形代码,用变量代替数值参数。
例如:
glRectf(-0.5,-0.5,0.5,0.5)改为glRectf(x1,y1,x2,y2);
程序前面加上变量声明和初始值,如:
floatx1=-0.5,y1=-0.5,x2=0.5,y2=0.5;注意语句的位置。
(3)在程序中增加mykeyboard键盘子函数,可放在display()函数之后。
并在如下代码中进行修改,实现键盘控制矩形移动,运行程序自行测试。
voidmykeyboard(unsignedcharkey,intx,inty)
{
switch(key)
{case'W':
case'w':
//矩形对角坐标变量修改使得矩形上移
y1+=0.1;y2+=0.1;
break;
case'S':
case's':
//矩形对角坐标变量修改使得矩形下移
y1-=0.1;y2-=0.1;
break;
case'A':
case'a':
//矩形对角坐标变量修改使得矩形左移
x1-=0.1;x2-=0.1;
break;
case'D':
case'd':
//矩形对角坐标变量修改使得矩形右移
x1+=0.1;x2+=0.1;
break;
}
//参数修改后调用重画函数,屏幕图形将发生改变
glutPostRedisplay();
}
图2-2
3、设置窗口改变函数,使得矩形的长度和宽度等于100,程序启动时矩形仍在窗口中央,当显示窗口最大化时,绘制矩形也随之增大,如图2-3。
(1)在main函数里添加注册窗口变化函数
glutReshapeFunc(myreshape);(放在glutMainLoop()之前)
并在程序头部声明添加窗口变换函数:
voidmyreshape(GLsizeiw,GLsizeih);
(2)在程序中添加窗口改变子函数,参数w,h为当前显示窗口的宽和高
voidmyreshape(GLsizeiw,GLsizeih)
{
glViewport(0,0,w,h);//设置视区位置
glMatrixMode(GL_PROJECTION);//设置投影变换模式
glLoadIdentity();//调单位矩阵,清空当前矩阵堆栈
gluOrtho2D(0,300,0,300);
}
3)此时,矩形的初始变量经重新计算后为:
floatx1=100,x1=100,x2=200,y2=200;
注意:
请同学们自己思考为什么矩形初始的初始变量由原来的(-0.5,-0.5,0.5,0.5)变为(100,100,200,200)?
裁剪窗口设置函数gluOrtho2D(xwmin,xwmax,ywmin,ywmax);和视区设置函数glViewport(startx,starty,viewport_width,viewport_height)的设置有何规律?
此时,按下键盘“WADS”键进行交互移动,矩形的移动距离较之前有什么变化?
要保持以前的移动频率,程序应该如何修改?
a)显示窗口改变前b)显示窗口变大后
图2-3
4、在矩形中间添加字符"Hello",观察结果;然后将"Hello"字符改为自己名字的拼音或英文名字。
如图2-4所示。
提示:
在绘制矩形后添加如下代码:
glColor3f(1,0,0);
glRasterPos2i((x1+x2)/2,(y1+y2)/2);//定位当前光标
glutBitmapCharacter(GLUT_BITMAP_9_BY_15,'H');//写字符"H"
glutBitmapCharacter(GLUT_BITMAP_9_BY_15,'e');//写字符"e"
glutBitmapCharacter(GLUT_BITMAP_9_BY_15,'l');//写字符"l"
glutBitmapCharacter(GLUT_BITMAP_9_BY_15,'l');//写字符"l"
glutBitmapCharacter(GLUT_BITMAP_9_BY_15,'o');//写字符"o"
注意:
运行程序,效果如图2-4所示。
但是如果此时,按下键盘“WADS”键进行交互移动,程序会发生什么变化?
要保持矩形白色,字符红色,程序应该如何修改?
如果字符颜色设置语句glColor3f(1,0,0);放在定位光标语句glRasterPos2i((x1+x2)/2,(y1+y2)/2);之后,运行又会发生什么变化?
请同学自己总结设置字符颜色语句的顺序规律。
图2-4
5、自己参照讲义或教材按照自己的构思画二维平面图形,将上面的矩形替换成自己构思的二维平面图形实现交互功能,注意顶点的顺序。
并在画面上标注自己的姓名。
3.2鼠标交互
(1)鼠标画线
阅读OpenGL鼠标画线程序,能够实现在绘制窗口用鼠标交互绘制若干条直线,鼠标左键首先按下,确定直线的起始点,鼠标左键按下同时移动,看到画线过程,鼠标左键松开时,确定直线的终点,可重复画多条直线。
实现主要思路:
1)写出画静止若干条直线程序框架,坐标用变量替代;
2)在主函数里注册鼠标按钮响应函数和鼠标移动响应函数;
3)在鼠标按钮响应子函数里,给出鼠标按钮响应事件;
4)在鼠标移动响应子函数里,给出鼠标移动响应事件;
5)读懂程序并分析程序,保留程序。
//鼠标画线小程序
#include"stdafx.h"
#include
#defineN1000//maximumlinenumbers
intww,hh;//fordisplaywindowwidthandheight
intline[N][4],k=0;//forline'sendpointcoordinatesandlinenumber
voidMyinit(void);
voidReshape(intw,inth);
voidmyMouse(intbutton,intstate,intx,inty);
voidmyMotion(intx,inty);
voidDisplay(void);
voiddrawlines();
intAPIENTRY_tWinMain(HINSTANCEhInstance,
HINSTANCEhPrevInstance,
LPTSTRlpCmdLine,
intnCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
char*argv[]={"hello",""};
intargc=2;//must/shouldmatchthenumberofstringsinargv
glutInit(&argc,argv);//初始化GLUT库;
glutInitWindowSize(800,600);//设置显示窗口大小
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);//设置显示模式;(注意双缓冲)
glutCreateWindow("鼠标画线小程序演示");//创建显示窗口
Myinit();
glutDisplayFunc(Display);//注册显示回调函数
glutMouseFunc(myMouse);//注册鼠标按钮回调函数
glutMotionFunc(myMotion);//注册鼠标移动回调函数
glutReshapeFunc(Reshape);//注册窗口改变回调函数
glutMainLoop();//进入事件处理循环
return0;
}
voidMyinit(void)
{
glClearColor(0.0,0.0,0.0,0.0);
glLineWidth(3.0);
}
//渲染绘制子程序--------------------------------------------------------------------------
voidDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT);//刷新颜色缓冲区;
drawlines();//画线子程序;
glutSwapBuffers();//双缓冲的刷新模式;
}
//-----------------------------------------------
voidReshape(intw,inth)//窗口改变时自动获取显示窗口的宽w和高h
{
glMatrixMode(GL_PROJECTION);//投影矩阵模式
glLoadIdentity();//矩阵堆栈清空
glViewport(0,0,w,h);//设置视区大小
gluOrtho2D(0,w,0,h);//设置裁剪窗口大小
ww=w;
hh=h;
}
//鼠标按钮响应事件..
voidmyMouse(intbutton,intstate,intx,inty)
{
if(button==GLUT_LEFT_BUTTON&&state==GLUT_DOWN)
{
line[k][0]=x;//线段起点x坐标
line[k][1]=hh-y;//线段终点y坐标
}
if(button==GLUT_LEFT_BUTTON&&state==GLUT_UP)
{
line[k][2]=x;//线段起点x坐标
line[k][3]=hh-y;//线段终点y坐标
k++;
glutPostRedisplay();
}
}
//鼠标移动时获得鼠标移动中的坐标-----------------------------------------------------
voidmyMotion(intx,inty)
{
//gettheline'smotionpoint
line[k][2]=x;//动态终点的x坐标
line[k][3]=hh-y;//动态终点的y坐标
glutPostRedisplay();
}
//画线子程序
voiddrawlines()
{
for(inti=0;i<=k;i++)//********
{
glBegin(GL_LINES);
glVertex2f(line[i][0],line[i][1]);
glVertex2f(line[i][2],line[i][3]);
glEnd();
}
}
鼠标画线程序运行后,程序效果如图3-3所示。
图3-3
(2)鼠标绘制矩形(将此修改代码贴到实验报告中)
修改鼠标画线程序,要求:
能够实现在绘制窗口用鼠标交互绘制若干矩形,鼠标左键首先按下,确定矩形对角线的起始点,鼠标左键按下同时移动时,看到画矩形过程,鼠标左键松开,确定矩形对角线的另一点,可重复画多个矩形。
如图3-4所示。
图3-4
四、思考题:
按下列步骤操作,并分析裁剪窗口、视区和显示窗口的关系。
(1)修改视区大小为原来的一半。
如图2-5(a)。
(2)修改裁剪窗口的大小原来的一半;视区保持不变。
如图2-5(b)。
图2-5(a)图2-5(b)
(3)修改以上程序使得按数字1键实现矩形用WSAD键控制上下左右移动,按2键显示自己构思的其他2D图形(三角形,点或多边形等)用WSAD键控制上下左右移动
五、参考函数:
1、裁剪窗口设置函数:
gluOrtho2D(xwmin,xwmax,ywmin,ywmax);
xwmin,xwmax,ywmin,ywmax为裁剪窗口在世界坐标系的位置,分别为x最小,x最大,y最小,y最大
2、视区设置函数:
glViewport(startx,starty,viewport_width,viewport_height);
绘图区在显示窗口中的位置,以屏幕坐标系为参考
startx,starty,viewport_width,viewport_height分别为绘图区在显示窗口的起点位置,以及绘图区的宽度和高度
3、键盘响应相关函数:
3.1glutKeyboardFunc(void*f(unsignedcharkey,intx,inty))
注册键盘响应函数,按下键盘中某键,程序将’key’值作为字符返回给函数f,用户可决定下一步的行动。
该函数调用放在主程序main()中
⏹例如,当用户按下’q’或’Q’或Esc键(ASCII27)时,程序退出。
⏹glutKeyboardFunc(mykey);//主函数注册键盘响应函数
⏹voidmykey((unsignedcharkey,intx,inty)//键盘响应函数
⏹{if(key==‘q’||key==‘Q’||key==‘\27’)
⏹exit(0);
⏹}
3.2特殊键响应
voidglutSpecialFunc(void(*f)(intkey,intx,inty))
当用户按下一个特殊键时,调用函数f响应用户需求。
使用方法同glutKeyboardFunc(void*f(unsignedcharkey,intx,inty))
例,if(key==GLUT_KEY_F1)….
if(key==GLUT_KEY_UP)….
非ASCII键
回调参数值
Fi(i=1,2,…,12)
GLUT_KEY_Fi
PageUp
GLUT_KEY_PAGE_UP
PageDown
GLUT_KEY_PAGE_DOWN
左方向键
GLUT_KEY_LEFT
右方向键
GLUT_KEY_RIGHT
上方向键
GLUT_KEY_UP
下方向键
GLUT_KEY_DOWN
Home
GLUT_KEY_HOME
End
GLUT_KEY_END
3.3组合键intglutGetModifers()
在键盘响应事件中当键盘按下时返回GLUT_ACTIVE_SHIFT,GLUT_ACTIVE_CTRL,或GLUT_ACTIVE_ALT值
例,if((glutGetModifers()==GLUT_ACTIVE_CTRL)&&((key==‘c’)||(key==‘C’)))exit(0);
4、鼠标按钮响应相关函数
⏹voidglutMouseFunc(void(*f)(intbutton,intstate,intx,inty))
☐Mousecallbackfunction。
在主程序中调用。
☐button:
⏹GLUT_LEFT_BUTTON,GLUT_MIDDLE_BUTTON,GLUT_RIGHT_BUTTON
☐state:
⏹GLUT_UP,GLUT_DOWN
☐x,y:
返回鼠标在窗口的位置(原点在左上角)。
例如,
主程序注册:
glutMouseFunc(mymouse);
voidmymouse(intx,inty,intbutton,intstate)
{
if(state==GLUT_DOWN&&button==GLUT_LEFT_BUTTON)
exit();//按下左键退出
}
5、注册鼠标移动响应函数
voidglutMotionFunc(void(*f)(intx,inty))
该函数在主程序中调用。
(x,y)鼠标的位置,原点在左上角
⏹moveevent:
鼠标按钮按下时的鼠标移动
☐glutMotionFunc(mymousemotion);
mymousemotion(intx,inty)
{
···//鼠标移动时触发的事件代码
}
⏹passivemoveevent:
鼠标按钮松开时的鼠标移动
☐glutPassveMotionFunc(mymousepmotion);
⏹entryevent:
鼠标进入或离开窗口时的事件
☐glutEntryFunc(mymouseentry);
⏹voidglutEntryFunc(void(*f)(intstate))
⏹x,y-鼠标的位置,原点在左上角
⏹state:
GLUT_ENTEREDorGLUT_LEFT
例,鼠标绘制折线代码
⏹鼠标按下时开始画折线,鼠标按钮松开时结束。
glutMotionFunc(mymotion);
voidmymotion(intx,inty)
{。
。
。
if(first_time_called)
glBegin(GL_LINE_STRIP);
glVertex2f(sx*(GLfloat)x,sy*(GLfloat)(h-y));
。
。
。
}
⏹注意:
鼠标按钮松开时产生glEnd()
六、实验演示录像
1.win32_lab3_interactive.exe
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验三 OpenGL的简单交互绘制new 实验 OpenGL 简单 交互 绘制 new