Использование OpenGL glutDisplayFunc в классе

Я создал класс C ++ ( myPixmap ) для инкапсуляции работы, выполняемой инструментарием OpenGL GLUT. Функция-член display () класса содержит большую часть кода, необходимого для настройки GLUT.


void myPixmap::display()
{
    // open an OpenGL window if it hasn't already been opened
    if (!openedWindow)
    {
        // command-line arguments to appease glut
        char *argv[] = {"myPixmap"};
        int argc = 1;
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
        glutInitWindowSize(640, 480);
        glutInitWindowPosition(30, 30);
        glutCreateWindow("Experiment");
        glutDisplayFunc(draw);
        glClearColor(0.9f, 0.9f, 0.9f, 0.0);
        glClear(GL_COLOR_BUFFER_BIT);
        glutMainLoop();

        openedWindow = true;
    }  
}

Функция отображения, переданная в glutDisplayFunc () , является другой функцией-членом класса :


void myPixmap::draw(void)
{
    glDrawPixels( m,n,GL_RGB,GL_UNSIGNED_BYTE, pixel );
}

Однако gcc 4.2.1 в Mac OS X 10.6.4 отказывается компилировать этот код, утверждая, что:

аргумент типа 'void (myPixmap ::) ()' не соответствует 'void (*) ()»

Есть ли способ использовать инструментарий GLUT внутри функции-члена класса, или я должен вызывать все функции GLUT в функции main программы?

27
задан Nicholas Kinar 28 August 2010 в 04:06
поделиться

1 ответ

Проблема в том, что указатель на связанную с экземпляром функцию-член должен включать указатель this. OpenGL — это C API, и он ничего не знает об указателях this. Вам придется использовать статическую функцию-член (которая не требует экземпляра и, следовательно, не this) и установить некоторые статические элементы данных (для доступа к экземпляру), чтобы использовать GlutDisplayFunc.

class myPixmap
{
private:
  static myPixmap* currentInstance;

  static void drawCallback()
  {
    currentInstance->draw();
  }

  void setupDrawCallback()
  {
    currentInstance = this;
    ::glutDisplayFunc(myPixmap::drawCallback);
  }
};

У вас также могут возникнуть проблемы с компоновкой C и компоновкой C++, и в этом случае вам придется поиграть с extern "C". Если это так, вам, возможно, придется использовать глобальную функцию, а не статическую функцию-член в качестве обратного вызова, и иметь этот вызов myPixmap::draw. Что-то вроде:

class myPixmap
{
public:
  void draw();

private:
  void setupDrawCallback();
};

myPixmap* g_CurrentInstance;

extern "C"
void drawCallback()
{
  g_CurrentInstance->draw();
}

void myPixmap::setupDrawCallback();
{
  ::g_CurrentInstance = this;
  ::glutDisplayFunc(::drawCallback);
}

При всем при этом старайтесь вносить как можно меньше изменений, так как это действительно своего рода кладж, чтобы иметь дело с OpenGL, являющимся C API.

Если вам нужно несколько экземпляров (я не думаю, что большинство людей, использующих GLUT, создают несколько экземпляров, но, возможно, вы это делаете), вам придется найти решение, используя std::map для получения экземпляра:

static std::map<int, myPixmap> instanceMap;

Я не уверен, где вы получите int для разрешения какого экземпляра :)

К вашему сведению, вы должны определить функции, которые не принимают никаких параметров:

void some_function() { }

not

void some_function(void) { }
33
ответ дан 28 November 2019 в 05:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: