资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,Angel:Interactive Computer Graphics 3E Addison-Wesley 2002,*,计算机图形学,杨 武,影像科学与技术实验室,东南大学计算机学院,yangwu,2,第三章,输入与交互,3,第三章之第一节,简 介,4,基本内容,常见的输入设备,物理设备,逻辑设备,输入模式,事件驱动的输入,光滑动画中的双缓存,用,GLUT,进行事件输入编程,6,图形输入设备,输入设备可以用下述两种属性中的一种进行描述,物理属性,鼠标 键盘 跟踪球,逻辑属性,设备通过,API,返回给程序的内容是什么?,位置,对象标识,7,物理设备,mouse,trackball,light pen,data tablet,joy stick,space ball,8,输入值,数据板等类似设备直接向操作系统返回位置,类似于鼠标、跟踪球以及游戏操纵杆等设备向操作系统返回一个步进输入,(,即速度,),必须把这些输入累加在一起得到一个绝对位置,鼠标滚轮的旋转,跟踪球的滚动,难以得到绝对位置,输入可能相当敏感,9,逻辑设备,考虑,C,与,C+,代码,C+:,cin x;,C:,scanf(“%d”,输入设备是什么,?,键盘、文件、,不管物理设备是什么,程序得到一个数,(int),作为输入,10,图形逻辑设备,在,GKS,和,PHIGS,中,定义了六种逻辑输入:,定位,:,返回一个位置,拾取,:,返回对象的标识,ID,字符串,:,返回字符串,笔划,:,返回位置数组,定值,:,返回浮点数,选择,:,返回,n,项中的一项,11,输入模式,如何以及何时获取输入?,触发器,(trigger),向操作系统发送一个信息,鼠标上的按钮、键盘上的键,测量值,当触发后,输入设备向系统返回信息,鼠标返回位置信息,键盘返回,ASCII,代码,请求,(,主动,),或者事件,(,被动,),12,请求模式,只有当用户触发了设备后,输入才提供给程序,典型例子:键盘输入,13,采样模式,程序需要输入函数调用时,输入设备立刻返回测量值,要求之前已经将输入数据存入缓存,14,事件模式,绝大部分系统具有多个输入设备,每个设备都可能被用户在任意时间触发,每个触发生成一个事件,事件的测量值放到事件队列中,用户程序检查该队列,15,事件类型,窗口:改变尺寸、重新显示、缩成图标,鼠标:点击一个或多个按钮,移动,键盘:按下或释放某个键,空闲:“没有事件”,可以定义如果队列中没有其它事件就可以进行的某种操作,16,回调,回调是事件驱动输入方式的程序界面,为图形系统可以识别的每种类型事件定义一个回调函数,当相应的事件出现时,就会自动执行用户指定的函数,GLUT,示例,:,glutMouseFunc(mymouse),鼠标回调函数,17,GLUT,中的回调函数,GLUT,识别在各种窗口系统,(Windows,X,Macintosh),中都有的一组事件,glutDisplayFunc,glutMouseFunc,glutReshapeFunc,glutKeyboardFunc,glutIdleFunc,glutMotionFunc,glutPassiveMotionFunc,18,GLUT,中的事件循环,记住,:,在任何利用,GLUT,的程序中,,main(),的最后一行实质语句必须是,glutMainLoop();,这条语句使得程序进入一个无穷的事件循环,每经过事件循环一次,,GLUT,进行下述操作,查看事件队列中的事件,对于在队列中的每个事件,如果定义了相应的回调函数,,GLUT,就执行这个回调函数,如果对该事件没有定义回调函数,那么就忽略该事件,19,显示回调函数,只要,GLUT,确定需要刷新窗口,那么就会执行显示回调函数,例如,第一次打开窗口,窗口形状改变,重新露出窗口,用户程序决定需要改变显示内容,在,main(),中,glutDisplayFunc(mydisplay),确定要执行的显示回调函数,每个,GLUT,程序都必须有一个显示回调函数,必要时可以设置为空函数,20,标识重新显示,许多事件都会导致调用显示回调函数,这会导致遍历一次事件循环的过程中多次执行显示回调函数,可以用下列方法避免这个问题,glutPostRedisplay();,这条语句设置一个标志,当事件循环结束时,,GLUT,会检查是否设置了上述标志,如果设置了标志,那么就会执行显示回调函数,21,空闲回调的应用,当在事件队列中没有事件时,就执行该回调函数,glutIdleFunc(myidle),动画中非常有用,void myidle(),/*change something*/,t+=dt,glutPostRedisplay();,void mydisplay(),glClear();,/*,根据,t,绘制图形,*,/,glutSwapBuffers();,22,全局变量的应用,所有,GLUT,回调函数的调用形式是固定的,void,mydisplay(),void,mymouse(GLint button,GLint state,GLint x,GLint y),为了向回调函数传递信息,必须应用全局变量,float t;/*,全局变量*,/,void mydisplay(),/*,根据,t,绘制图形*,/,23,动画,当通过显示回调函数重新绘制显示结果时,我们通常会首先清除整个窗口:,glClear(),然后再绘制已发生了变化的显示结果,问题:帧缓冲区中的信息在显示器上的显示结果出现了错位,图形系统可以同时向显存中写入内容和从中读出内容,24,双缓存,不只用一个颜色缓冲区,而是应用两个缓冲区,前缓冲区,:,:显示它的内容,但不向它写入内容,后缓冲区,:写入内容,不显示,程序在,main(),中请求使用双缓存,glutInitDisplayMode(GL_RGB|GL_DOUBLE),在显示回调函数结束之前,交换两个缓冲区,void mydisplay(),glClear();,/*,绘制图形,*,/,glutSwapBuffers();,
展开阅读全文