在类中使用 OpenGL glutDisplayFunc

2021-12-19 00:00:00 opengl class compiler-errors c++

我创建了一个 C++ 类 (myPixmap) 来封装由 OpenGL GLUT 工具包执行的工作.类的 display() 成员函数包含设置 GLUT 所需的大部分代码.

I've created a C++ class (myPixmap) to encapsulate the work performed by the OpenGL GLUT toolkit. The display() member function of the class contains most of the code required to set up 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()的显示函数是该类的另一个成员函数:

The display function passed to glutDisplayFunc() is another member function of the class:


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

然而,Mac OS X 10.6.4 上的 gcc 4.2.1 拒绝编译此代码,声称:

However, gcc 4.2.1 on Mac OS X 10.6.4 refuses to compile this code, claiming that:

<代码>void (myPixmap::)()"类型的参数与void (*)()"不匹配

有没有办法在类的成员函数内使用 GLUT 工具包,或者我必须在程序的 main 函数内调用所有的 GLUT 函数?

Is there a way to use the GLUT toolkit inside a member function of a class, or must I call all GLUT functions within the main function of the program?

推荐答案

问题是指向实例绑定成员函数的指针必须包含 this 指针.OpenGL 是一个 C API,对 this 指针一无所知.您必须使用静态成员函数(它不需要实例,因此不需要 this),并设置一些静态数据成员(以访问实例)才能使用 glutDisplayFunc.

The problem is that a pointer to an instance bound member function has to include the this pointer. OpenGL is a C API, and knows nothing about this pointers. You'll have to use a static member function (which doesn't require an instance, and thus no this), and set some static data members (to access the instance) in order to use 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.类似的东西:

You may also have problems with C linkage vs C++ linkage, in which case you'll have to play around with extern "C". If so, you might have to use a global function, rather than a static member function as your callback, and have that call myPixmap::draw. Something like:

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 来说确实有点麻烦.

With all of this, try to make as few changes as possible, since this is really kind of a kludge to deal w/ OpenGL being a C API.

如果你想要多个实例(我认为大多数使用 GLUT 的人不会创建多个实例,但也许你是),你必须找出一个使用 std::map 来检索实例的解决方案:

If you want multiple instances (I don't think most people using GLUT make multiple instances, but maybe you are), you'll have to figure out a solution using a std::map to retrieve the instance:

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

从哪里获得 int 来解析 哪个 实例,我不确定:)

Where you'd get the int to resolve which instance, I am not sure :)

仅供参考,您应该以这种方式定义不带参数的函数:

FYI, you should define functions that take no parameters this way:

void some_function() { }

不是

void some_function(void) { }

相关文章