对于最终项目,我和我的朋友正在制作一个游戏。我们正在使用 GLUT(我知道,这不是最佳选择)。我们想做的是针对游戏的不同模式(例如启动画面、菜单画面、游戏画面等)有多个显示回调函数,所以当游戏模式改变时,我们改变回调。glutDisplayFunc
所以实际上,它有点像在 GLUT 运行时能够调用。这可能吗?我们不愿意在整体显示函数中使用巨大的 if/switch 语句,因为我们认为它可能会影响性能。如果这种担心是没有根据的,请说出来!
4 回答
glutDisplayFunc 将指向显示场景的指针作为参数。使用多个显示函数最简单的方法是简单地调用 glutDisplayFunc 与您要切换到的显示场景函数指针。
IE
void render1() {
//.. display something
}
void render2() {
//.. display something else
}
//...
void someEvent() {
if(iWantToRender1) {
glutDisplayFunc(render1);
glutIdleFunc(render1);
} else {
glutDisplayFunc(render2);
glutIdleFunc(render2);
}
}
这与在 render1/render2 中使用 if/else 不同,因为它会更改要调用的函数。如果您查看 GLUT 的文档,http: //www.opengl.org/resources/libraries/glut/spec3/node46.html glutDisplayFunc 会更改当前窗口的显示功能,而不是执行类似 glutTimerFunc 之类的操作,后者会安排要运行的内容。
这个问题有点老了,但我偶然发现了这个答案,同时为完全相同的问题寻找解决方案。
我认为,更优雅的方法是使用函数指针。首先,您创建一个函数指针(可能是全局的):
void (*foo)(void);
之后,您可以创建不同的绘图功能,例如:
void draw_1()
{
/* Draw fancy stuff */
}
void draw_2()
{
/* Draw other fancy stuff */
}
现在你需要一个“mainloop-mainloop”函数,它由 glutMainLoop 调用,它引用你的指针:
void mainloop_mainloop()
{
(*foo)();
}
正如我所说,这个函数必须是你的 glutMainLoop,所以你设置它:
glutDisplayFunc(mainloop_mainloop);
glutIdleFunc(mainloop_mainloop);
当然,您必须在某处设置函数指针:
foo = &draw_1;
如果您现在希望切换到另一个绘图上下文,您只需更改指针。例如,您可以在菜单中实现此功能:
if (menuentry==1) foo = &draw_1;
if (menuentry==2) foo = &draw_2;
等等……
这使您能够留在 glut 主循环内而不会弄乱显示功能,并且性能也不会受到损害,因为您只设置了一次 if/switch。您只有一个额外的函数调用,考虑到用于在每一帧中绘制您的东西的函数调用的数量,这应该可以忽略不计......
我们不愿意在整体显示函数中使用巨大的 if/switch 语句,因为我们认为它可能会影响性能。
它当然不是最好的编码风格,但性能不是一个论据。
您可以制作自己的模拟系统glutDisplayFunc
,例如epicGameDisplayFunc
将函数指针更改为传递的函数。
这段代码对我来说很好用。首先在 int main() 中,您必须调用第一个显示,然后添加 glutTimerFunc,您可以在一定时间后调用另一个显示。
void MyTimerFunc(int value);
int main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH);
glutInitWindowSize(700,500);
glutInitWindowPosition(0,0);
glutCreateWindow("Animated Road Crossing Alert System");
initOpenGl();
glutDisplayFunc(display);
glutIdleFunc(display);
glutTimerFunc(20000, MyTimerFunc, 0);
glutMainLoop();
return 0;
}
void MyTimerFunc(int value)
{
if (value == 0) // passed in in main
{
glutDisplayFunc(display1);
glutIdleFunc(display1);
// Change to a new display function in 2 seconds
glutTimerFunc(40000, MyTimerFunc, 1);
}
else if(value==1)
{
glutDisplayFunc(display2);
glutIdleFunc(display2);
}
}