重绘回调函数

    void glutReshapeFunc(void(*f)(int width,int height))

    当用户用鼠标改变窗口的尺寸时,窗口回调函数f()即被调用,然后调用显示回调函数。新窗口的h和w将返回函数f()

    

    注:窗口首次创建时,重回回调函数也将被调用。


Idle回调函数

    void glutIdleFunc(void(*f)(void))

    当事件对列为空时,函数f()将得到执行。


    void glutPostRedisplay()

    请求在当前回调函数返回之后,执行回调函数。


    下面给出一个矩形旋转的例子

#include <gl/glut.h>
#include <math.h>

#define DEG_TO_RAD 0.017453

GLfloat theta=0.0;

void init()
{
	glClearColor(0.0,0.0,0.0,0.0);      //指定屏幕背景为黑色

	glColor3f(1.0,1.0,1.0);             //设置绘制颜色为白色

	glShadeModel(GL_FLAT);              //设置颜色插值为平面模式


}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT);         //清理屏幕颜色为我们指定的颜色

	glBegin(GL_POLYGON);              //绘制模式为凸多边形
	glVertex2f(-cos(DEG_TO_RAD*theta),-sin(DEG_TO_RAD*theta));
	glVertex2f(sin(DEG_TO_RAD*theta),-cos(DEG_TO_RAD*theta));
	glVertex2f(cos(DEG_TO_RAD*theta),sin(DEG_TO_RAD*theta));
	glVertex2f(-sin(DEG_TO_RAD*theta),cos(DEG_TO_RAD*theta));
	glEnd();                          

	glFlush();                       //强制以上绘图操作执行
}

void reshape(int w,int h)
{
	glMatrixMode(GL_PROJECTION);       //设置为投影模式
	glLoadIdentity();
	gluOrtho2D(-1.0,1.0,-1.0,1.0);

	glViewport(0,0,(GLsizei)w,(GLsizei)h);
}

void myidle()
{
	theta+=2.0;
	if(theta>360) theta-=360;
	glutPostRedisplay();
}

int main(int argc,char**argv)
{
	glutInit(&argc,argv);                           //初始化glut
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);    //设置窗口模式为单缓冲和RGB模式
	glutInitWindowSize(500,500);                    //设置窗口大小
	init();
	glutCreateWindow("test");                       //设置窗口标题
	glutDisplayFunc(display);                       //设置绘图回调函数
	glutReshapeFunc(reshape);                       //设置窗口回调函数
	glutIdleFunc(myidle);                           //设置空闲回调函数
	glutMainLoop();                                 //开始循环,等待响应
	return 0;
}

    运行程序得到如下结果:

     OpenGL学习(二)用户与交互_OpenGL


双缓存

      使用两个颜色缓存--前台缓存的后台缓存,前台缓存时显示硬件所显示的内容,而后台缓存则是     应 用程序进行绘制的地方。后台缓存绘制玩整个正方形后,我们要做的仅仅是交换这两个缓存的内     容。在显示回调函数中用函数glutSwapBuffers()代替glFluash()即可。

      注:该函数是一个glut函数,交换过程中涉及与窗口系统的交互。因此必须在初始化阶段请求双     缓存模式,即glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB)。


键盘的使用

    void glutKeyboardFunc(void* f(unsigned char key,int x,int y))

    指定当任何键被按下,函数f将被调用。所按下的建同光标的位置一并传入f。光标位置为像素,从

    窗口左上角开始度量的。

    注:该函数只响应按下的操作,释放按键的消息将被忽略。


特殊键

    void glutSpecialFunc(void* f(unsigned char key,int x,int y))

    指定特殊键的回调函数。

    如:

        if(key == GLUT_KEY_F1)

        if(key == GLUT_KEY_UP)


    int glutGetModifiers()

    如果键在鼠标或键盘事件产生时,键被按下,则该函数返回GLUT_ACTIVE_SHIFT,GLUT_ACTIVE_CTRL     或者GLUT_ACTIVE_ALT的逻辑与结果。


    例如为了让Ctrl+c或C种植一段程序,则可这样写:

    if(glutGetModifiers()==GLUT_ACTIVE_CTRL && ((key=='c') || (key='C'))) exit(0);


鼠标回调函数

    void glutMouseFunc(void (*f)(int button,int state,int x,int y))

        表明三件事:鼠标回调函数f返回鼠标在窗口的位置、其状态(GLUT_UP或GLUT_DOWN)以及鼠标事       件的来源(GLUT_LEFT_BUTTON,GLUT_MIDDLE_BUTTON 或 GLUT_RIGHT_BUTTON)

    

鼠标的移动

    当鼠标移动,无论键是否被按下,也会引发事件。

     移动事件:键被按下鼠标移动(move event)。

     被移动事件:移动时未有键被按下(passive move event);


    void glutMotionFunc(void (*f)(int x,int y))

    void glutPassiveMotionFunc(void (*f)(int x,int y))

    指定移动和被移动事件的回调函数,鼠标的位置(x,y)返回给这两个函数


    当鼠标进入或里考OpenGL窗口时将产生一个进入事件

    void glutEntryFunc(void (*f)(int state))

    指定进入回调函数,返回的状态为GLUT_ENTERED或GLUT_LEFT。


一个鼠标移动,根据鼠标绘制曲线的例子

#include <gl/glut.h>
#include <math.h>
#include <vector>
#include <iostream>

using namespace std;

int hh;       //获取屏幕的高

vector<pair<int,int>> v;          //将每次鼠标移动的点放入v中

void init()
{
	glClearColor(0.0,0.0,0.0,0.0);      //指定屏幕背景为黑色

	glColor3f(1.0,1.0,1.0);             //设置绘制颜色为白色

	glShadeModel(GL_FLAT);              //设置颜色插值为平面模式

}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT);         //清理屏幕颜色为我们指定的颜色
	

	glBegin(GL_LINE_STRIP);              //绘制模式为线
	for (vector<pair<int,int>>::iterator it=v.begin();it!=v.end();it++)     //绘制v中的每个顶点   
	{
		pair<int,int> p=*it;
		glVertex2i(p.first,p.second);
	}
	glEnd();                          

	glFlush();                       //强制以上绘图操作执行
}

void reshape(int w,int h)
{
	glMatrixMode(GL_PROJECTION);       //设置为投影模式
	glLoadIdentity();
	gluOrtho2D(0,w,0,h);
	
	glViewport(0,0,(GLsizei)w,(GLsizei)h);
	hh=h;
}


void mymotion(int x,int y)
{
	v.push_back(make_pair(x,hh-y));   //每次把鼠标移动的点存入v中,注意y是以左上角为原点
	glutPostRedisplay();             //重绘
}

void mouse(int button,int state,int x,int y)
{
	if (state==GLUT_DOWN) v.clear();   //每次按下鼠标即清除原来v中的数据
	glutPostRedisplay();          //重绘
}

int main(int argc,char**argv)
{
	glutInit(&argc,argv);                           //初始化glut
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);    //设置窗口模式为单缓冲和RGB模式
	glutInitWindowSize(500,500);                    //设置窗口大小
	init();
	glutCreateWindow("test");                       //设置窗口标题
	glutDisplayFunc(display);                       //设置绘图回调函数
	glutReshapeFunc(reshape);                       //设置窗口回调函数
	glutMotionFunc(mymotion);                       //设置移动回调函数
	glutMouseFunc(mouse);							//设置鼠标回调函数
	glutMainLoop();                                 //开始循环,等待响应
	return 0;
}

运行得到如下结果:

    OpenGL学习(二)用户与交互_ 用户交互 _02