Переключение обратного вызова дисплея в GLUT - PullRequest
1 голос
/ 08 мая 2011

Для финального проекта мы с друзьями делаем игру. Мы используем GLUT (я знаю, не лучший выбор). Мы хотели бы иметь несколько функций обратного вызова дисплея для различных режимов игры (например, заставки, экрана меню, экрана игрового процесса и т. Д.), Поэтому при изменении режима игры мы изменяем обратный вызов. По сути, это похоже на возможность вызова glutDisplayFunc во время работы GLUT. Это возможно? Мы неохотно имеем гигантский оператор if / switch в общей функции отображения, поскольку считаем, что это может снизить производительность. Если это беспокойство необоснованно, скажите, пожалуйста!

Ответы [ 4 ]

2 голосов
/ 08 мая 2011

glutDisplayFunc принимает указатель на сцену дисплея в качестве аргумента.Самый простой способ использовать несколько функций отображения - просто вызвать glutDisplayFunc с указателем на функцию отображения сцены, на которую вы хотите переключиться.

т.е.

void render1() {
    //.. display something
}

void render2() {
    //.. display something else
}

//...
void someEvent() {
    if(iWantToRender1) {
        glutDisplayFunc(render1);
        glutIdleFunc(render1);
    } else {
        glutDisplayFunc(render2);
        glutIdleFunc(render2);
    }
}

Это отличается от использования if / elseв render1 / render2, потому что он меняет какую функцию вызывать.Если вы посмотрите документацию GLUT, http://www.opengl.org/resources/libraries/glut/spec3/node46.html glutDisplayFunc изменяет функцию отображения текущего окна, а не выполняет что-то вроде glutTimerFunc, которая планирует что-то для запуска.

1 голос
/ 03 апреля 2012

Этот вопрос довольно старый, но я наткнулся на этот ответ, пытаясь найти решение точно такой же проблемы.

Думаю, более элегантным подходом было бы использование указателей на функции.Сначала вы создаете указатель на функцию (может быть глобальным):

void (*foo)(void);

, после этого вы создаете различные функции рисования, например:

void draw_1()    
{    
  /* Draw fancy stuff */
}

void draw_2()
{
  /* Draw other fancy stuff */
}

Теперь вам нужен "mainloop-mainloop "-функция, которая вызывается glutMainLoop an и ссылается на ваш указатель:

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;

и т. Д. *

Это позволяет вам оставаться в главном цикле перенасыщения, не путая функции дисплея и выиграв производительностьЭто также не повредит, так как вы устанавливаете if / switch только один раз.У вас есть только один дополнительный вызов функции, который следует пренебречь, учитывая количество вызовов функций, используемых для прорисовки ваших кадров в каждом отдельном кадре ...

0 голосов
/ 04 июля 2018

Этот код работает нормально для меня.Сначала в 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);
   }

}
0 голосов
/ 08 мая 2011

Мы не хотим иметь гигантское выражение if / switch в общей функции отображения, потому что мы думаем, что это может снизить производительность.

Конечно, это не лучший стиль кодирования, но производительность не является аргументом.

Вы можете создать свою собственную систему, которая имитирует glutDisplayFunc, например epicGameDisplayFunc, которая изменяет указатель функции на переданную функцию.

...