Использование OpenGL glutDisplayFunc в классе - PullRequest
25 голосов
/ 28 августа 2010

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

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

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

Ответы [ 4 ]

32 голосов
/ 28 августа 2010

Проблема в том, что указатель на функцию-член, связанную с экземпляром, должен включать указатель 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);
  }
};

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

не

void some_function(void) { }
4 голосов
/ 27 мая 2013

Пожалуйста, проверьте этот урок, я думаю, это то, что вы ищете: http://paulsolt.com/2010/08/glut-object-oriented-framework-on-github/

2 голосов
/ 01 ноября 2013

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

Class myPixmap;
static myPixmap* currentInstance;
Class myPixmap {
...
}
1 голос
/ 16 июня 2015

У меня были проблемы с пониманием правильного ответа от Мерлина, поэтому вот упрощенная версия:

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

class myPixmap
{
  //...
  static void display();
  //...
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...