zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    cnpm镜像安装
    wxParse解析html
    C++回调函数
    QT源码分析:QTcpServer
    QT实现支持加密的Sqlite数据库引擎
    VS2013+OpenCV3.4.2编译
    Android Tcp操作
    使用Delphi开发linux应用
    QT5.10+MinGW+OpenCV3.4.2编译
    C++ ActiveX开发的问题讨论
  • 原文地址:https://www.cnblogs.com/CooCoo/p/5304150.html
Copyright © 2011-2022 走看看