Подтвердить что ты не робот

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

Я создал класс С++ (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 отказывается компилировать этот код, утверждая, что:

argument of type 'void (myPixmap::)()' does not match 'void (*)()'

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

4b9b3361

Ответ 1

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

class myPixmap
{
private:
  static myPixmap* currentInstance;

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

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

У вас могут также возникнуть проблемы с C linkage vs С++ linkage, и в этом случае вам придется играть с 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);
}

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

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

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

Если вы получили int, чтобы разрешить этот экземпляр, я не уверен:)

FYI, вы должны определить функции, которые не принимают никаких параметров таким образом:

void some_function() { }

не

void some_function(void) { }

Ответ 3

Решение Merlyn не работало для меня, поэтому я сделал небольшую модификацию, добавив currentInstance вне класса, и это сработало:

Class myPixmap;
static myPixmap* currentInstance;
Class myPixmap {
...
}

Ответ 4

У меня возникла проблема в понимании правильного ответа от Merlyn, так что это упрощенная версия:

В myPixmap.h измените функцию отображения на статическую функцию-член. Должен работать.

class myPixmap
{
  //...
  static void display();
  //...
};