如果你自己都不清楚所談論的東西,就根本不可能精確的描述它——馮諾依曼
今天我就試著來表述一件眾人皆知的事情,以測試自己到底有沒有明白這件事情。
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");
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_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( )
此時我們會考慮,如果我們想要新增乙個例子,應該如何去做? 於是,我們需要先看看sample_skybox 以及sampleplugin.
開啟sample_skybox.h 我們便會看到
class _ogresampleclas***port 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即可。
OGRE 1 7 例子程式分析
如果你自己都不清楚所談論的東西,就根本不可能精確的描述它 馮諾依曼 今天我就試著來表述一件眾人皆知的事情,以測試自己到底有沒有明白這件事情。ogre 是著名的設計模式大師,這已是不爭的事實。可以說 ogre 裡將設計模式用得淋漓盡致。在這裡我就不批判設計模式該不該用了。反正 ogre 已經用了,並且...
ogre1 7中文路徑bug處理
ogre1.7在編譯完成後,執行例子時,在完成配置介面後,會出現乙個錯誤對話方塊 顯示ogreroot.cpp line 382 錯誤。經過除錯發現,ogre要向 我的文件 寫ogre的配置資訊,就是配置介面中設定的資訊,而在本人的電腦上,我的文件 這個資料夾的路徑是 d backup 我的文件 若...
多型(二) 例子
有乙個動物類,1.0版本只有吃 睡得方法。而1.1時代動物類就有了很多子類,這些子類都有他們各自吃睡得方法,但是行為跟父類是一樣的,屬於方法的過載。因為動物太多了,我可以每次都去建立物件,但是每次呼叫物件的方法都是相同的過程,所以1.2時代,我可以把這個過程抽取出來,放在另外乙個工具類中,把我每次呼...