• 编写Ogre插件的一般方法


    转载请注明出处!Pulas

     http://www.cnblogs.com/pulas/archive/2012/02/18/2357663.html

            Ogre的插件可以是动态链接库,也可以是静态链接库。若是动态链接库,则可通过在插件配置文件(默认为plugins.cfg)里添加插件名称,然后在创建Root时,会在Root的构造函数里通过Root::loadPlugin(const String& pluginName)方法遍历加载每一个插件。也可通过Root::loadPlugin(const String& pluginName)方法手动加载自定义插件。

            当Root::loadPlugin(const String& pluginName)函数被调用时,Ogre将加载该插件的dll,并从中查找并调用名为dllStartPlugin()的导出函数。对应的,当Root::unloadPlugin(const String& pluginName)函数被调用时,Ogre将从该dll中调用dllStopPlugin()函数,并将该dll卸载。所以每个插件在实现的时候,都必须提供上述的两个C导出函数。其中,dllStartPlugin()负责创建插件实例,并调用Root::installPlugin(),将创建好的插件指针传递给Root对象。在这里,dllStartPlugin()实际可以创建多个插件实例,并依次调用Root::installPlugin(),这样我们就可以在一个dll中包含多个插件了。在dllStopPlugin()时,则需要调用 Root::uninstallPlugin(),并将插件dll中创建的plugin实例释放掉。所以,若要实现一个四叉树的场景管理器插件,则必须先实现这两个C导出函数。

    #include <OgreRoot.h>
    #include <QuadtreePlugin.h>
    
    #ifndef OGRE_STATIC_LIB
    
    namespace Ogre
    {
    QuadtreePlugin* quadtreePlugin;
    
    extern "C" void _QuadtreePluginExport dllStartPlugin( void )
    {
        // Create new scene manager
        quadtreePlugin = OGRE_NEW QuadtreePlugin();
    
        // Register
        Root::getSingleton().installPlugin(quadtreePlugin);
    }
    extern "C" void _QuadtreePluginExport dllStopPlugin( void )
    {
    	Root::getSingleton().uninstallPlugin(quadtreePlugin);
    	OGRE_DELETE quadtreePlugin;
    }
    }
    
    #endif

    在上述dllStartPlugin( void )函数中创建自定义插件。Ogre定义了一个抽象的Plugin插件接口,每一个插件都必须实现该插件接口。

    	class _OgreExport Plugin : public PluginAlloc
    	{
    	public:
    		Plugin() {}
    		virtual ~Plugin() {}
    
    		/** Get the name of the plugin. 
    		@remarks An implementation must be supplied for this method to uniquely
    			identify the plugin.
    		*/
    		virtual const String& getName() const = 0;
    
    		/** Perform the plugin initial installation sequence. 
    		@remarks An implementation must be supplied for this method. It must perform
    		the startup tasks necessary to install any rendersystem customisations 
    		or anything else that is not dependent on system initialisation, ie
    		only dependent on the core of Ogre. It must not perform any
    		operations that would create rendersystem-specific objects at this stage,
    		that should be done in initialise().
    		*/
    		virtual void install() = 0;
    
    		/** Perform any tasks the plugin needs to perform on full system
    			initialisation.
    		@remarks An implementation must be supplied for this method. It is called 
    			just after the system is fully initialised (either after Root::initialise
    			if a window is created then, or after the first window is created)
    			and therefore all rendersystem functionality is available at this
    			time. You can use this hook to create any resources which are 
    			dependent on a rendersystem or have rendersystem-specific implementations.
    		*/
    		virtual void initialise() = 0;
    
    		/** Perform any tasks the plugin needs to perform when the system is shut down.
    		@remarks An implementation must be supplied for this method.
    		This method is called just before key parts of the system are unloaded, 
    		such as rendersystems being shut down. You should use this hook to free up 
    		resources and decouple custom objects from the OGRE system, whilst all the
    		instances of other plugins (e.g. rendersystems) still exist.
    		*/
    		virtual void shutdown() = 0;
    
    		/** Perform the final plugin uninstallation sequence. 
    		@remarks An implementation must be supplied for this method. It must perform
    		the cleanup tasks which haven't already been performed in shutdown()
    		(e.g. final deletion of custom instances, if you kept them around incase
    		the system was reinitialised). At this stage you cannot be sure what other
    		plugins are still loaded or active. It must therefore not perform any
    		operations that would reference any rendersystem-specific objects - those
    		should have been sorted out in the 'shutdown' method.
    		*/
    		virtual void uninstall() = 0;
    	};

    Root::getSingleton().installPlugin(plugin)会负责调用插件的install()操作,并将插件的指针存放起来,以备卸载时使用。Root::initialise()会负责调用插件的initialise()操作。

    Plugin::install()以及Plugin::initialise()则分别负责创建OgreMain提供扩展功能接口的实例,以及将创建好的对象挂载到应用程序当中。

    Root:: shutdown()会负责调用插件的shutdown()操作。Root::getSingleton().uninstallPlugin(plugin)会负责调用插件的uninstall()操作。

    使用插件时几个需要注意的地方:

    1. 调用插件DLL方法创建的对象需要交由插件DLL释放。(因为不同的链接单元可能具有不同的内存管理上下文环境,此处的new与彼处的new在语义上未必等同)

    2. 调用插件DLL方法获取的插件内对象的引用或指针,在插件DLL卸载之后就是无效的,必须保证不再使用。(比较容易引发问题的一个典型例子是从插件中传递回一个引用计数字符串,当DLL被卸载后,字符串内指向实际数据的指针已经无效,但是在该对象析构时,仍需要访问该指针)

    若插件是静态链接库,则可在任何时候创建插件,然后在创建Root后,调用Root::installPlugin(plugin)安装插件。手动调用Root::uninstallPlugin(plugin)卸载插件。

    可以参考Ogre Wiki上的教程:

    http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Creating+A+Plugin+DLL

    Final Thoughts

      
    It's up to you to do what you want inside the plugin, and keep in mind that it can be used to create plugins for your own game or application specific purposes. For example, in my game engine and editor most major pieces of functionality are loaded as plugins, including game objects, game systems, scene partitions, tool plugins for the editor, etc. All you need to do is have a clear set of base classes, a factory and a factory manager.

    For example a simplified Factory system:

    GameObject class in the plugin:

    class GameObject
    {
      void tick(float deltaTime);
    };

      
    Class factory that creates GameObjects in the plugin:

    class GameObjectFactory
    {
      virtual bool supportsGameObjectType(const String& objectType) = 0;
      virtual GameObject* createGameObject(const String& objectType) = 0;
    };

      
    A manager class (in the game) that we can register factories with that will be used to create game objects:

    class GameObjectFactoryManager : public Singleton<GameObjectFactoryManager>
    {
      void registerGameObjectFactory(GameObjectFactory* factory)
      {
        //add factory to an array
      }
      void unregisterGameObjectFactory(GameObjectFactory* factory)
      {
        //find and remove factory from mFactories
      }
      GameObject* createGameObject(const String& objectType)
      {
        //find a factory that supports this object type and then call createGameObject() on it
      }
    };

      
    You could now create new classes that derive from GameObject, such as MeshGameObject, and a factory that creates those objects such as MeshGameObjectFactory, and have your application create a GameObjectFactoryManager at startup. Then have a plugin that callsGameObjectFactoryManager::getSingleton().registerGameObjectFactory(meshGameObjectFactory) during its initialise() call. Then from your game you can now create instances of new MeshGameObjects dynamically without ever having linked to the DLL.

  • 相关阅读:
    事件(五):事件委托
    事件(四):事件类型
    【[ZJOI2005]午餐】
    【[POI2006]OKR-Periods of Words】
    【2^k进制数】
    【[SHOI2015]脑洞治疗仪】
    【[NOI2016]区间】
    【[SHOI2014]概率充电器】
    【逛公园】
    【[CQOI2014]数三角形】
  • 原文地址:https://www.cnblogs.com/pulas/p/2357663.html
Copyright © 2020-2023  润新知