实验三 OpenGL的简单交互绘制new.docx

上传人:b****6 文档编号:7359595 上传时间:2023-01-23 格式:DOCX 页数:16 大小:74.91KB
下载 相关 举报
实验三 OpenGL的简单交互绘制new.docx_第1页
第1页 / 共16页
实验三 OpenGL的简单交互绘制new.docx_第2页
第2页 / 共16页
实验三 OpenGL的简单交互绘制new.docx_第3页
第3页 / 共16页
实验三 OpenGL的简单交互绘制new.docx_第4页
第4页 / 共16页
实验三 OpenGL的简单交互绘制new.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

实验三 OpenGL的简单交互绘制new.docx

《实验三 OpenGL的简单交互绘制new.docx》由会员分享,可在线阅读,更多相关《实验三 OpenGL的简单交互绘制new.docx(16页珍藏版)》请在冰豆网上搜索。

实验三 OpenGL的简单交互绘制new.docx

实验三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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 教学研究 > 教学案例设计

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1