opengl 里面的 callback function
一、回调函数的意义:
打个比方,有一家旅馆提供叫醒服务,但是要求旅客自己决定叫醒的方法。可以是打客房电话,也可以是派服务员去敲门,睡得死怕耽误事的,还可以要求往自己头上浇盆水。这里,“叫醒”这个行为是旅馆提供的,相当于库函数,但是叫醒的方式是由旅客决定并告诉旅馆的,也就是回调函数。而旅客告诉旅馆怎么叫醒自己的动作,也就是把回调函数传入库函数的动作,称为 登记回调函数(to register a callback function)。
可以说,回调函数就是在main函数里调用函数,但是传的参数是之前定义的函数。
二、callback function 在opengl中的应用
#include <GLUT/GLUT.h>
typedef struct {GLfloat x, y;} point;
point p0={0,50};
GLfloat finishx=300;
void display(void){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 600, 0, 400);
glClearColor(0, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 1, 1);
glBegin(GL_LINES);
glVertex2f(finishx, 50);
glVertex2f(finishx, 350);
glEnd();
glColor3f(0, 1, 0);
glBegin(GL_POLYGON);
glVertex2f(0,0);
glVertex2f(0,50);
glVertex2f(600,50);
glVertex2f(600,0);
glEnd();
glColor3f(1,0,0);
glBegin(GL_POLYGON);
glVertex2f(p0.x,p0.y);
glVertex2f(p0.x,p0.y+20);
glVertex2f(p0.x+30,p0.y+20);
glVertex2f(p0.x+30,p0.y);
glEnd();
glutSwapBuffers();
}
//task2
GLfloat step=10; // declare step
int time_interval=16; // declare refresh interval in ms
void when_in_mainloop() { // idle callback function
glutPostRedisplay(); // force OpenGL to redraw the current window
}
void OnTimer(int value) {
p0.x+=step;
if(p0.x>=600)
p0.x=0;
else if(p0.x<=0)
p0.x=599;
// when_in_mainloop();
glutTimerFunc(time_interval, OnTimer, 1);
}
//task3
void keyboard_input(unsigned char key, int x, int y) {// keyboard interaction
if(key=='q' || key=='Q')
exit(0);
else if(key=='f' || key=='F')// change direction of movement
step=-step;
else if(key=='s' || key=='S')// stop
step=0;
else if(key=='r' || key=='R')// set step
step=10;
}
//task4
void mouse_input(int button, int state, int x, int y) { // mouse interaction
if(state==GLUT_DOWN && button==GLUT_LEFT_BUTTON && step>=-15)
step-=1; // decrement step
else if(state==GLUT_DOWN && button==GLUT_RIGHT_BUTTON && step<=15)
step+=1; // increment step
}
int main(int argc,char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowPosition(100,100);
glutInitWindowSize(600,400);
glutCreateWindow("My Interactive Window");
glutDisplayFunc(display);
//Task 2
glutIdleFunc(when_in_mainloop);
/* glutIdleFunc sets the global idle callback to be func so a GLUT program
can perform background processing tasks or continuous animation when window
system events are not being received.
If enabled, the idle callback is continuously called when events are not
being received. The callback routine has no parameters. The current window
and current menu will not be changed before the idle callback. Programs with
multiple windows and/or menus should explicitly set the current window and/or
current menu and not rely on its current setting. The amount of computation
and rendering done in an idle callback should be minimized to avoid affecting
the program's interactive response. In general, not more than a single frame
of rendering should be done in an idle callback.
Assigning NULL to glutIdleFunc disables the generation of the idle
callback.*/
glutTimerFunc(time_interval,OnTimer,1);
//
//Task 3
glutKeyboardFunc(keyboard_input);
//Task 4
//
glutMouseFunc(mouse_input);//mouse callback function
glutMainLoop();
}
这里值得注意的是:
每一次callback function被调用是相当于重新调用了一次main函数 但是传参不同。
三、编写代码时的一点小心得
c++和java类似,一个文件里只能有一个main函数,所以虽然配环境很困难,但是每次有新的任务还是得重新建个文件,而且记得不要重复命名!