OGRE 1.7 例子程序分析

如果你自己都不清楚所谈论的东西,就根本不可能精确的描述它——冯诺依曼

 

今天我就试着来表述一件众人皆知的事情,以测试自己到底有没有明白这件事情。

 

OGRE是著名的设计模式大师,这已是不争的事实。可以说OGRE里将设计模式用得淋漓尽致。在这里我就不批判设计模式该不该用了。反正OGRE已经用了,并且没有出现什么不好的结果。适合的就是最好的,OGRE证明了这一点。

 

随着OGRE  1.7的发布,大家熟悉的DEMO程序不见了,换来的是一个个的DLL库。而这些库,就是作为OGRE的一个插件而存在。拿SkyBox为例,(不要问为什么拿SkyBox,如果真要知道,我只能说,我刚好看上它了。)我们可以在SkyBox.cpp里发现如下代码。

 

 

SamplePlugin* sp;

Sample* s;

extern "C" _OgreSampleExport void dllStartPlugin()

{

    s = new Sample_SkyBox;

    sp = OGRE_NEW SamplePlugin(s->getInfo()["Title"] + " Sample");

    sp->addSample(s);

    Root::getSingleton().installPlugin(sp);

}

extern "C" _OgreSampleExport void dllStopPlugin()

{

    Root::getSingleton().uninstallPlugin(sp); 

    OGRE_DELETE sp;

    delete s;

}

 

 

 

 

dllStartPlugin  和 dllStopPlugin 是插件的加载和卸载接口。可以看到,当调用dllStartPlugin 时,它先新建了一个Sample_SkyBox实例,这就是我们真正的示例程序。紧接着,它又新建了一个插件。插件的名字则以实例的Title信息加上Sample来标志。随后,这个示例程序的实例被加入插件中,然后调用Root::getSingleton().installPlugin(sp);函数初始化我们的插件。

 

显然,我们需要看看installPlugin干了些什么。

 

 

    void Root::installPlugin(Plugin* plugin)

    {

        LogManager::getSingleton().logMessage("Installing plugin: " + plugin->getName());

        mPlugins.push_back(plugin);

        plugin->install();

        // if rendersystem is already initialised, call rendersystem init too

        if (mIsInitialised)

        {

            plugin->initialise();

        }

        LogManager::getSingleton().logMessage("Plugin successfully installed");

    }

 

 

 

 

不难看出,OGRE在这个函数中将插件加入了自己的插件容器中,并调用插件的初始化接口。以及输出相关LOG信息。

 

而又是在何时调用这个dllStartPlugin来加载插件的呢。我们打开SampleBrowser.h找到virtual Sample* loadSamples()函数。在这个函数中的前几句便反应了它所做的工作。

 

 

Sample* startupSample = 0;

Ogre::StringVector unloadedSamplePlugins;

Ogre::ConfigFile cfg;

cfg.load(mFSLayer->getConfigFilePath("samples.cfg"));

Ogre::String sampleDir = cfg.getSetting("SampleFolder");        // Mac OS X just uses Resources/ directory

Ogre::StringVector sampleList = cfg.getMultiSetting("SamplePlugin");

Ogre::String startupSampleTitle = cfg.getSetting("StartupSample");

 

 

 

 

在这里,例子浏览器加载了samples.cfg文件,并读取相关内容。我们看看samples.cfg 里装了些什么便一切明了了。

 

 

SampleFolder=.

SamplePlugin=Sample_BezierPatch_d

SamplePlugin=Sample_BSP_d

SamplePlugin=Sample_CameraTrack_d

SamplePlugin=Sample_CelShading_d

SamplePlugin=Sample_Character_d

SamplePlugin=Sample_Compositor_d

SamplePlugin=Sample_CubeMapping_d

SamplePlugin=Sample_DeferredShading_d

。。。。

 

 

 

 

这些正好是我们的例子插件的DLL文件名。loadSamples函数在读取了这些信息后,将其放入 StringVector sampleList 中,然后依次遍历这个容器,并调用插件加载函数。代码如下

 

// loop through all sample plugins...

for (Ogre::StringVector::iterator i = sampleList.begin(); i != sampleList.end(); i++)

{

    mRoot->loadPlugin(sampleDir + *i);

}

 

 

 

 

按照我们分析问题的方案(我们总是从程序的行为进行跟踪分析)。于是我们看看loadPlugin函数做了些什么。

 

 

    void Root::loadPlugin(const String& pluginName)

    {

    //根据名字加载动态库

        DynLib* lib = DynLibManager::getSingleton().load( pluginName );

     //查找是否已经加载,如果没有存在,则加入其中。并且取得入口函数并执行。

        if (std::find(mPluginLibs.begin(), mPluginLibs.end(), lib) == mPluginLibs.end())

        {

            mPluginLibs.push_back(lib);

            DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol("dllStartPlugin");

            if (!pFunc)

                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Cannot find symbol dllStartPlugin in library " + pluginName,

                    "Root::loadPlugin");

            pFunc();//执行dllStartPlugin( )

        }

    }

 

 

 

 

由此,我们便可以知道整个程序的流程。。即例子浏览器在初始化时读取samples_d.cfg文件,然后根据文件内容加载所有的DLL并初始化相关内容。

 

此时我们会考虑,如果我们想要新增一个例子,应该如何去做?于是,我们需要先看看Sample_SkyBox 以及SamplePlugin.

 

打开Sample_SkyBox.h 我们便会看到

 

class _OgreSampleClassExport Sample_SkyBox : public SdkSample

{

protected:

    void setupContent()

    {

    //实现代码

     }

};

 

 

 

上面代码说明了,Sample_SkyBox继承自SdkSample,并且实现了setupContent函数。

我们再打开SamplePlugin可以看到有些空函数,说明在我们的例子中,SamplePlugin并没有做太多的初始化工作。于是,我们得到如下的关系

 

1、      Sample_SkyBox派生自SdkSample

2、      SamplePlugin派生自Plugin

3、      SamplePlugin持有Sample_SkyBox实例指针

4、      SamplePlugin会注册到Root的插件管理中

5、      Sample_SkyBox应该被加入到Samples_d.cfg中。

 

于是,我们可以看到,如果我们想实现一个简单的例子。则只需要自SdkSample派生一个实现类,并至少实现setupContent函数。然后学着Sample_SkyBox的样子写好dllStartPlugin和dllStopPlugin函数,并导出成DLL,然后将DLL名字添加到smaples_d.cfg中。

 

以上描述均是Debug版本下。如果是Release,则去掉后面的_d即可。

作者:码瘾少年·麒麟子 
出处:http://www.cnblogs.com/geniusalex/ 
蛮牛专栏:麒麟子 
简介:09年入行,喜欢游戏和编程,对3D游戏和引擎尤其感兴趣。 
版权声明:本文版权归作者和博客园共有,欢迎转载。转载必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载:http://www.cnblogs.com/geniusalex/archive/2010/07/15/1940475.html

时间: 2024-11-02 10:36:00

OGRE 1.7 例子程序分析的相关文章

《程序分析方法》——2.2 元程序设计系统

2.2 元程序设计系统 2.2.1 元程序系统的组成 元程序的处理对象是程序而不是通常的数据,因此其处理过程要相对复杂.通常一个元程序设计系统由下面三个部分构成: 预处理--把目标程序变成一种中间表示(目标语言的内部表示形式). 元级操作--对内部表示直接进行处理的基本操作. 后处理--把中间表示转化为目标代码. 其中,中间表示决定了该系统中目标程序到元级用户的接口特性,对整个系统的可用性起到重要作用:而元级操作是系统的另一重要部分,用户主要使用这些元级操作对目标程序的内部表示进行处理(注意,此

java中有关get方法的使用(具体程序分析)

问题描述 java中有关get方法的使用(具体程序分析) 最近在学习java,用的徐彩霞的java基础教程. 有个例子不太明白. /* /注释部分的get部分有和没有结果一样,想知道为什么要用get? 又必须要用的情况吗? 刚学,懂得比较少,谢谢了~ class Person { private String name; private int age; private void talk() { System.out.print("I'm "+name+" and &quo

《程序分析方法》——第2章 元程序设计 2.1 元程序介绍

第2章 元程序设计 2.1 元程序介绍 1.元程序概念 在现代程序设计中,程序已经取代数据成为操作对象,变得越来越重要.元级程序设计系统是一种对程序进行操作的有效工具,可用于各种元程序设计.其中,对程序进行处理的基本操作称为元级操作:实现元级操作的语言叫做元语言:所处理的语言叫做目标语言. 元程序(Meta Program)是可以操作目标程序(Object Program)的程序,它可以构造目标程序,也可以将目标程序段组合成更大的目标程序,还可以观察目标程序的结构和其他特性.目标程序是以形式语言

SDL2.0例子代码分析---代码运行平台检测

简介 SDL2.0例子程序中的 testplatform项目代码分析 ,针对不同的平台 检测字节序 CPU支持的指令集 类型宽度 以及断言 代码+注释 #include <stdio.h> #include "SDL.h" #include "SDL_endian.h" #include "SDL_cpuinfo.h" #include "SDL_assert.h" /* * 该例子代码检测运行平台 */ //判断

SDL2.0例子代码分析-----CheckKeys Project

SDL简介 SDL(Simple DirectMedia Layer)是一套开放源代码的跨平台多媒体开发库,使用C语言写成.SDL提供了数种控制图像.声音.输出入的函数,让开发者只要用相同或是相似的代码就可以开发出跨多个平台(Linux.Windows.Mac OS X等)的应用软件.目前SDL多用于开发游戏.模拟器.媒体播放器等多媒体应用领域. SDL1.2和SDL2的差别 SDK1.2和SDL2.1系列的API接口变动的不小,当然功能也大大增强,支持多线程窗口. 具体的change 请看 h

关于继承内部类——java编程思想示例程序分析

编程|程序|继承|示例 关于继承内部类--java编程思想示例程序分析:class Egg2 { protected class Yolk { public Yolk() { System.out.println("Egg2.Yolk()"); } public void f() { System.out.println("Egg2.Yolk.f()"); } } private Yolk y = new Yolk(); public Egg2() { System

java-Android-JAVA程序分析,帮忙分析下以下程序如何拆行,怎么分析。

问题描述 Android-JAVA程序分析,帮忙分析下以下程序如何拆行,怎么分析. public class ja { private Bundle metaData; public void doit() { String str3 = config("sapi_sign", "e56b4eb0473d219c5317afb7ccf66e8f"); System.out.println(str3); } private String config(String p

Freemarker 最简单的例子程序_java

Freemarker 最简单的例子程序   freemarker-2.3.18.tar.gz http://cdnetworks-kr-1.dl.sourceforge.net/project/freemarker/freemarker/2.3.18/freemarker-2.3.18.tar.gz freemarker-2.3.13.jar: 链接: http://pan.baidu.com/s/1eQVl9Zk 密码: izs5 1.通过String来创建模版对象,并执行插值处理 执行后,控

WEB容器调用spark程序分析数据

问题描述 WEB容器调用spark程序分析数据 请教各位大神,如何在web容器中(如tomcat)来调用spark程序啊,网上看到的都是自己把程序生成jar包,然后调用spark-submit来执行!! 解决方案 楼主的问题是怎么解决的,我们现在也要这么做,能不能给点指导,小弟在这先谢谢了 解决方案二: 可以参考 一下 这个 http://www.aboutyun.com/thread-11014-1-1.html