openGL中的函数调用类成员函数

做图形学作业终于到的问题。打算将每一个场景抽象为一个Scene类,然后调用类的run接口来显示场景。

其中遇到了关于glutDisplayFunc函数调用的问题,函数原型为:

extern void APIENTRY glutDisplayFunc(void (*func)(void));

即要求func参数为一个void (*func)(void)类型,对于如下定义的类:

class Scene
{
    public:
        Scene(std::string title, int width=1024, int height=768);
        virtual ~Scene();
        /*初始化场景*/
        virtual void init(int argc, char *argv[]) = 0;
        /*运行场景*/
        virtual int run() = 0;
    protected:
        /*绘制场景*/
        virtual void display() = 0;
        /*键盘回调函数*/
        virtual void key(unsigned char key, int x, int y) = 0;
        virtual void reshape(int width, int height) = 0;
        virtual void idle() = 0;
};

那么我需要传入的是Scene::display函数,此时将会出现函数类型不匹配的问题。因为Scene::display为Scene类的成员函数,类成员函数的实现方式是传入了一个默认的Scene *this参数,所以如果要使用成员函数,必须同时传入this指针,这与func类型冲突。

参考stackoverflow上的解决方法1:http://stackoverflow.com/questions/3589422/using-opengl-glutdisplayfunc-within-class

将Scene设计为一个单例类,定义static void displayCallback()函数,内部通过单例指针调用display函数,通过这种添加中间层的方式将带有默认this指针的函数转变为全局可访问的 void (*func)(void)函数。但其付出的代价就是不能创建多个场景实例,不过目前所做的是一个单场景,并不需要考虑此问题。

修改后代码如下:

/*
file:Scene.h
brief:创建一个opengl场景
*/
#ifndef SCENE_H
#define SCENE_H

#include <string>

#include "opengl.h"

class Scene
{
    public:
        Scene(std::string title, int width=1024, int height=768);
        virtual ~Scene();
        /*初始化场景*/
        virtual void init(int argc, char *argv[]) = 0;
        /*运行场景*/
        virtual int run() = 0;

        void setupDisplayCallback()
        {
            currentInstance = this;
            ::glutDisplayFunc(Scene::displayCallback);
        }

        void setupKeyCallback()
        {
            currentInstance = this;
            ::glutKeyboardFunc(Scene::keyCallback);
        }
        void setupReshapeCallback()
        {
            currentInstance = this;
            ::glutReshapeFunc(Scene::reshapeCallback);
        }
        void setupIdleCallBack()
        {
            currentInstance = this;
            ::glutIdleFunc(Scene::idleCallback);
        }

        static void displayCallback()
        {
            currentInstance->display();
        }
        static void keyCallback(unsigned char key, int x, int y)
        {
            currentInstance->key(key, x, y);
        }
        static void reshapeCallback(int width, int height)
        {
            currentInstance->reshape(width, height);
        }
        static void idleCallback()
        {
            currentInstance->idle();
        }
    protected:
        std::string _title;
        int _height;
        int _width;

        /*绘制场景*/
        virtual void display() = 0;
        /*键盘回调函数*/
        virtual void key(unsigned char key, int x, int y) = 0;
        virtual void reshape(int width, int height) = 0;
        virtual void idle() = 0;
    private:
        static Scene * currentInstance;
};
#endif // SCENE_H
原文地址:https://www.cnblogs.com/CooCoo/p/5304150.html