实验四 OpenGL的简单动画与交互
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验四 OpenGL的简单动画与交互
一、实验目的
1、学会OpenGL的简单键盘交互操作。
2、掌握OpenGL鼠标交互功能及其简单应用。
3、掌握OpenGL的闲置函数与简单动画。
4、掌握反走样思想和算法。
二、实验内容与要求
1、在实验一(画矩形)的基础上添加键盘交互,按W键绘制的矩形上移,
按S键矩形下移,按A键矩形左移,按D键矩形右移,如图3-1。
参考
步骤如下:
(1)在主函数里添加键盘注册回调函数
glutKeyboardFunc(mykeyboard);
此函数可放在 glutDisplayFunc(display);后面。
(2)在display()绘制函数中修改绘制矩形代码,用变量代替数值参数。
例如: glRectf(-0.5,-0.5,0.5,0.5)改为glRectf(x1,y1,x2,y2);
(3)在程序中增加mykeyboard键盘子函数,并在如下代码中进行修改,实现键盘控制矩形移动
void mykeyboard(unsigned char key, int x, int y)
{
switch(key)
{ case 'W':
case 'w':// 矩形对角坐标变量修改使得矩形上移 break;
case 'S':
case 's'://矩形对角坐标变量修改使得矩形下移 break;
case 'A':
case 'a'://矩形对角坐标变量修改使得矩形左移 break;
case 'D':
case 'd'://矩形对角坐标变量修改使得矩形右移 break;
}
//参数修改后调用重画函数,屏幕图形将发生改变
glutPostRedisplay();
}
2、闲置函数的使用与简单动画。
旋转的六边形,如图3-3所示
阅读OpenGL旋转的六边形样本框架程序rotate-polygon.cpp,分
析程序的实现步骤:
//样本程序:旋转的六边形
#include<glut.h>
#include<math.h>
#define PI 3.14159 //设置圆周率
int n=6, R=10; //多边形变数,外接圆半径
float theta=0.0; //旋转初始角度值
void Keyboard(unsigned char key, int x, int y);
void Display(void);
void Reshape(int w, int h);
void myidle();
void main(int argc, char** argv)
{ glutInit(&argc, argv); //初始化GLUT库;
glutInitWindowSize(700,700); //设置显示窗口大小
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); //设置显示模式;(注意双缓冲)
glutCreateWindow("A Rotating Square"); // 创建显示窗口
glutDisplayFunc(Display); //注册显示回调函数
glutReshapeFunc(Reshape); //注册窗口改变回调函数
glutIdleFunc(myidle); //注册闲置回调函数
glutMainLoop(); //进入事件处理循环
}
void Display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,0,0); //设置红色绘图颜色
glBegin(GL_POLYGON); //开始绘制六边形
for (int i=0;i<n;i++)
glVertex2f( R*cos(theta+i*2*PI/n), R*sin(theta+i*2*PI/n));
glEnd();
glutSwapBuffers(); //双缓冲的刷新模式;
}
void myidle()
{
theta+=1.0;
if (theta>=2*PI) theta-=2*PI;
glutPostRedisplay(); //重画,相当于重新调用Display(),改编后的变量得以传给绘制函数}
void Reshape(GLsizei w,GLsizei h)
{
glMatrixMode(GL_PROJECTION); //投影矩阵模式
glLoadIdentity(); //矩阵堆栈清空
gluOrtho2D(-1.5*R*w/h,1.5*R*w/h,-1.5*R,1.5*R); //设置裁剪窗口大小
glViewport(0,0,w,h); //设置视区大小
glMatrixMode(GL_MODELVIEW); //模型矩阵模式
}
运行该程序,观察旋转动画效果。
思考: 如果要调整旋转速度,旋转更快或更慢,应该如何修改程序?
图3-3
3、鼠标交互。
(1) 鼠标画线
阅读OpenGL鼠标画线程序draw-lines.cpp,能够实现在绘制窗口
用鼠标交互绘制若干条直线,鼠标左键首先按下,确定直线的起始
点,鼠标左键按下同时移动,看到画线过程,鼠标左键松开时,确
定直线的终点,可重复画多条直线。
如图3-4所示。
图3-4
实现主要思路:
1) 写出画静止若干条直线程序框架,坐标用变量替代;
2) 在主函数里注册鼠标按钮响应函数和鼠标移动响应函数;
3) 在鼠标按钮响应子函数里,给出鼠标按钮响应事件;
4) 在鼠标移动响应子函数里,给出鼠标移动响应事件;
5) 读懂程序并分析程序,保留程序。
选做:(2) 鼠标绘制矩形
修改鼠标画线程序draw-lines.cpp,要求:能够实现在绘制窗口
用鼠标交互绘制若干矩形,鼠标左键首先按下,确定矩形对角线的
起始点,鼠标左键按下同时移动时,看到画矩形过程,鼠标左键松
开,确定矩形对角线的另一点,可重复画多个矩形。
如图3-5所示。
参考函数:
1、注册鼠标按钮响应函数
glutMouseFunc(void(*f)(int button,int state,int x,int y))
该函数在主程序中调用。
参数button:
GLUT_LEFT_BUTTON,GLUT_MIDDLE_BUTTON,GLUT_RIGHT_BUTTON 参数state:
GLUT_UP,GLUT_DOWN
x,y:返回鼠标在窗口的位置(原点在左上角)。
2、鼠标按钮响应回调函数
mymousebutton(int button, int state, int x, int y)
{
···
}
3、注册鼠标移动响应函数
void glutMotionFunc(void (*f) (int x,int y))
该函数在主程序中调用。
(x,y)鼠标的位置,原点在左上角
4、鼠标移动响应回调函数
mymousemotion(int x,int y)
{
···
}
图3-5
4、已知画线程序,在主程序中增加初始化子函数init(); 添加反走样代码和取
消抗锯齿代码,使得斜线变光滑。
可对比一下反走样效果:
按1键斜线锯齿(如图3-6),按2键斜线光滑(如图3-7)。
图3-6 图3-7
参考函数:
反走样代码,点、直线、多边形的抗锯齿:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_POINT_SMOOTH);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glEnable(GL_POLYGON_SMOOTH);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
取消抗锯齿:
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_POINT_SMOOTH);
glDisable(GL_POLYGON_SMOOTH);
选做:
5、程序合成。
要求:将以上4个小程序集成在一起,实现:
按下数字1键:清屏实现显示旋转的六边形
按下数字2键:清屏实现显示鼠标画线
按下数字3键:清屏实现显示鼠标绘制矩形
提示:1、增加keyboard()函数,同时在display()函数中添加switch 语句,实现每个数字键的不同功能。
2、记住清空堆栈,否则会对其他的实验结果产生影响。