青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Ogre源碼剖析3–可擴(kuò)展性&插件機(jī)制

 

Ogre是一個(gè)跨操作系統(tǒng)平臺(tái)的開源3D引擎,既支持DirectX,也支持使用OpenGL,支持可替換的場(chǎng)景管理算法(BSP, OCT)。為Ogre提供這些靈活可擴(kuò)展性的基礎(chǔ)之一就是其面向插件的設(shè)計(jì)。

 

很多常用的軟件大都提供了插件接口,用以擴(kuò)展應(yīng)用程序設(shè)計(jì)者最初未想到的功能,比較常見的譬如PhotoShop的濾鏡,After Effect中的各種插件(最有名的比如shine),3dMax的插件譬如渲染器,魔獸世界的輔助插件等等。

通常,插件本身通常也需要實(shí)現(xiàn)主應(yīng)用程序所需要的必要接口,從而使得插件可以被應(yīng)用程序加載執(zhí)行。此外,插件的實(shí)現(xiàn)也需要由主應(yīng)用程序提供一些接口api,通過這些接口,插件可以對(duì)主應(yīng)用程序的功能進(jìn)行調(diào)用。

插件可以是動(dòng)態(tài)鏈接庫(kù)(win32平臺(tái)上為DLL文件),也可以是以腳本的形式提供的,比如魔獸世界中的插件就是使用lua編寫的,插件也可能是某種應(yīng)用程序自定義的文件,只要該應(yīng)用程序提供了創(chuàng)建該類文件的方法并實(shí)現(xiàn)解析、執(zhí)行功能即可。(不同的實(shí)現(xiàn)形式各有利弊,具體需要參考插件及應(yīng)用程序所處的運(yùn)行環(huán)境進(jìn)行取舍)

采用插件的一個(gè)巨大的好處,以及很多應(yīng)用程序中使用插件的主要目的就是,我們可以在不需要改動(dòng)應(yīng)用程序本身的情況下擴(kuò)展應(yīng)用程序的功能。

 

在Ogre中,插件被用來提供渲染子系統(tǒng)(RenderSystem),不同類別的圖形API被封裝在不同的渲染子系統(tǒng)的視線當(dāng)中,Ogre默認(rèn)提供了DX和OpenGL的實(shí)現(xiàn),甚至,如果我們樂意,甚至可以只用繪點(diǎn)函數(shù)實(shí)現(xiàn)一套純軟件的渲染子系統(tǒng)提供給Ogre使用。以此為例,用簡(jiǎn)單的形式來展示這種實(shí)現(xiàn)大概類似于下面這樣:

class RenderSystem

{

         
// … operations that a render system need to support

};

// In DX_RenderSystem.dll (in plugin dx rendersystem )

class DX_RenderSystem : public RenderSystem

{

         
// … implementation & override of the operations from RenderSystem using DirectX

};

// In GL_RenderSystem.dll (in plugin openGL rendersystem)

class GL_RenderSystem : public RenderSystem

{

         
// … implementation & override of the operations from RenderSystem using OpenGL

};

// …. We could implement any other rendersystem as we like

 

在引擎的內(nèi)部(OgreMain),插件在初始化的時(shí)候,將一個(gè)渲染子系統(tǒng)的實(shí)例創(chuàng)建出來(可能是DX_RenderSystem,也可能是 GL_RenderSystem,也可能是其他),并將之掛接到OgreMain的Root對(duì)象當(dāng)中。此后,OgreMain中的Root所有的渲染操作也就可以通過該接口訪問插件中創(chuàng)建的渲染子系統(tǒng)了。

 

         本文接下來分析Ogre是如何實(shí)現(xiàn)插件的,以及插件是如何與OgreMain主引擎進(jìn)行配合的。

         事實(shí)上,想編寫一個(gè)插件是很簡(jiǎn)單的,我們只需要約定幾個(gè)接口,插件將這些接口實(shí)現(xiàn)了,主應(yīng)用程序通過某種機(jī)制(配置文件
/遍歷某個(gè)目錄)加載插件,并查找接口在插件中是否被實(shí)現(xiàn)了,如果實(shí)現(xiàn)了,則調(diào)用之即可。

 

一個(gè)簡(jiǎn)單的例子如下:

// in xx.dll

__declspec(dllexport) 
extern “C”    // __declspec(dllexport)告知編譯器需要將該函數(shù)導(dǎo)出

                                                                 
// extern “C” 告知編譯器不要對(duì)函數(shù)做C++名字重整

const char* GetPluginName(void)

{

         
return “Test Plugin”;

}

 

// in application

HMODULE hInst 
= LoadLibrary(”xx.dll”);

if (!hInst) return;

typedef 
const char* (*GetPluginNameFunc)(void);

GetPluginNameFunc pFunc 
= GetProcAddress(hInst, “GetPluginName”);

if (!pFunc) return;

const char* szPluginName = pFunc();

// … do other things

 

事實(shí)上,在C語言里,我們就可以通過這種方式,約定一套需要實(shí)現(xiàn)的接口,交給插件實(shí)現(xiàn)即可。在這里,插件的功能都是在dll中實(shí)現(xiàn)的,我們需要加載 dll,保存句柄,并在插件卸載的時(shí)候釋放相應(yīng)的資源。在C
++中,我們顯然可以做的更好一點(diǎn),比如將dll模塊相關(guān)的功能以及資源封裝起來:

 

class DynLib

{

public:

         
bool Load(const char* szPluginPath);

         
void* GetProcAddress(const char* szProcName);

private:

         HMODULE m_hInst;

};

 

bool DynLib::Load(const char* szPluginPath)

{

m_hInst 
= LoadLibrary(szPluginPath);

return m_hInst != NULL;

}

 

void* DynLib::GetProcAddress(const char* szProcName)

{

         
return ::GetProcAddress(m_hInst, szProcName);

}

 

這樣一來,我們就有了一個(gè)DLL的簡(jiǎn)單封裝。

但是一個(gè)dll里未必只能有一個(gè)插件,假若我們簡(jiǎn)單的把插件接口設(shè)計(jì)為一套C導(dǎo)出函數(shù),我們就不得不面對(duì)這種局限。經(jīng)典的做法依舊是抽象,Ogre中定義了一個(gè)插件接口,每一個(gè)實(shí)現(xiàn)了插件接口的實(shí)例都代表了一個(gè)插件,如下:

 

class Plugin

{

public:

         
virtual const String& getName() = 0;

         
virtual void install() = 0;

         
virtual void initialize() = 0;

         
virtual void shutdown() = 0;

         
virtual void uninstall() = 0;

};

 

Ogre的每一個(gè)插件都需要實(shí)現(xiàn)以上接口。該接口提供的功能包括:

install 插件被加載時(shí)調(diào)用。

initialize 插件被初始化時(shí)調(diào)用。

shutdown 插件被反初始化時(shí)調(diào)用。

uninstall 插件被卸載時(shí)調(diào)用。

 

不過,單有這個(gè)接口,插件還是無法工作。插件中還需要提供兩個(gè)約定的C導(dǎo)出函數(shù)。這個(gè)稍后再說。

 

Ogre在Root對(duì)象中統(tǒng)一管理插件,因此Root對(duì)象提供了以下與插件相關(guān)的接口:

class Root

{

         
// …

void loadPlugin(const String& pluginName);

void unloadPlugin(const String& pluginName);

void installPlugin(Plugin* plugin);

void uninstallPlugin(Plugin* plugin);

// 以及對(duì)應(yīng)的處理多個(gè)插件的接口

         
// …

};

 

當(dāng)loadPlugin函數(shù)被調(diào)用時(shí),Ogre將加載該插件的dll,從中查找并調(diào)用名為dllStartPlugin的導(dǎo)出函數(shù)。

對(duì)應(yīng)的,當(dāng)unloadPlugin函數(shù)被調(diào)用時(shí),Ogre將從該dll中調(diào)用dllStopPlugin函數(shù)。并將該dll卸載。

 

每個(gè)插件在實(shí)現(xiàn)的時(shí)候,都必須提供上述的兩個(gè)C導(dǎo)出函數(shù)。其中,dllStartPlugin負(fù)責(zé)創(chuàng)建插件實(shí)例,并調(diào)用 Root::installPlugin,將創(chuàng)建好的插件指針傳遞給Root對(duì)象。在這里,dllStartPlugin實(shí)際可以創(chuàng)建多個(gè)插件實(shí)例,并依次調(diào)用Root::installPlugin,這樣我們就可以在一個(gè)DLL中包含多個(gè)插件了。在dllStopPlugin時(shí),則需要調(diào)用 Root::uninstallPlugin,并將插件DLL中創(chuàng)建的plugin實(shí)例釋放掉。

 

一個(gè)典型的dllStartPlugin的實(shí)現(xiàn)像這樣:

 

class D3D9Plugin : public Plugin

{

         
//

};

 

D3D9Plugin
* plugin;

__declspec(dllexport) 
extern “C”

void dllStrartPlugin(void)

{

         plugin 
= new D3D9Plugin();

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

}

 

__declspec(dllexport) 
extern “C”

void dllStopPlugin(void)

{

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

delete plugin;

}

 

Root::getSingleton().installPlugin(plugin)會(huì)負(fù)責(zé)調(diào)用插件的install以及initialise操作,并將插件的指針存放起來,以備卸載時(shí)使用。

 

Plugin::install以及Plugin::initialise則分別負(fù)責(zé)創(chuàng)建OgreMain提供擴(kuò)展功能接口的實(shí)例,以及將創(chuàng)建好的對(duì)象掛載到應(yīng)用程序當(dāng)中。

 

一個(gè)典型的Plugin的行為像這樣:

 

void BspSceneManagerPlugin::install()

{

         mBspFactory 
= new BspSceneManagerFactory();

}

 

void BspSceneManagerPlugin::initialise()

{

         Root::getSingleton().addSceneManagerFactory(mBspFactory);

}

 

其中,BspSceneManagerFactory是繼承自O(shè)greMain中的SceneManagerFactory的派生類。

class BspSceneManagerFactory : public SceneManagerFactory {…} )

 

通過將場(chǎng)景管理器工廠添加到Root對(duì)象當(dāng)中,插件動(dòng)態(tài)的將其功能添加到了OgreMain當(dāng)中。

 

PS: SceneManagerFactory是一個(gè)用于創(chuàng)建SceneManager的工廠。SceneManager則是被用于場(chǎng)景管理的管理器。具體的 SceneManager也根據(jù)算法不同而不同,Ogre自帶提供了兩種類型的場(chǎng)景管理算法插件:Bsp以及Octree(實(shí)現(xiàn)了兩個(gè)對(duì)應(yīng)的插件,分別是 Plugin_BSPSceneManager以及Plugin_OctreeSceneManager)。

 

通過上述方式,OgreMain核心引擎并不需要關(guān)心場(chǎng)景管理算法的具體實(shí)現(xiàn),不需要關(guān)心渲染子系統(tǒng)的具體實(shí)現(xiàn),不需要關(guān)心粒子系統(tǒng)的具體實(shí)現(xiàn),等等。一切這些擴(kuò)展性的功能都通過插件實(shí)現(xiàn),并在加載時(shí)動(dòng)態(tài)掛載到OgreMain當(dāng)中,供OgreMain的引擎核心使用。

 

使用插件時(shí)幾個(gè)需要注意的地方:

1,  調(diào)用插件DLL方法創(chuàng)建的對(duì)象需要交由插件DLL釋放。(因?yàn)椴煌逆溄訂卧赡芫哂胁煌膬?nèi)存管理上下文環(huán)境,此處的new與彼處的new在語義上未必等同)

2,  調(diào)用插件DLL方法獲取的插件內(nèi)對(duì)象的引用或指針,在插件DLL卸載之后就是無效的,必須保證不再使用。(比較容易引發(fā)問題的一個(gè)典型例子是從插件中傳遞回一個(gè)引用計(jì)數(shù)字符串,當(dāng)DLL被卸載后,字符串內(nèi)指向?qū)嶋H數(shù)據(jù)的指針已經(jīng)無效,但是在該對(duì)象析構(gòu)時(shí),仍需要訪問該指針)

posts - 94, comments - 138, trackbacks - 0, articles - 94

Copyright © RichardHe

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            美女脱光内衣内裤视频久久影院| 午夜精品一区二区三区在线播放| 国产主播一区二区三区四区| 99精品热6080yy久久| 欧美一区午夜精品| 亚洲激情小视频| 欧美在线亚洲在线| 一区二区三区日韩在线观看| 国产欧美一区二区三区国产幕精品| 久久久久国产精品午夜一区| 亚洲欧美日韩综合国产aⅴ| 亚洲免费电影在线| 亚洲人成在线观看| 亚洲国产精品成人综合| 久热精品视频| 亚洲动漫精品| 亚洲国产精品999| 欧美在线在线| 久久一区二区视频| 久久九九热免费视频| 欧美一区二区三区四区在线观看地址 | 亚洲精品国偷自产在线99热| 国产一区二区视频在线观看| 国产一区二区三区日韩| 欧美日本一区二区视频在线观看| 久久久欧美一区二区| 久久久久久久久久久久久9999| 欧美一区二区三区的| 久久久久综合网| 欧美在线视频不卡| 欧美国产亚洲视频| 欧美精品黄色| 国产精品美女久久| 一区二区亚洲精品国产| 欧美成人高清| 国产嫩草一区二区三区在线观看| 免费黄网站欧美| 国产精品美女久久久久久久| 亚洲精品自在久久| 亚洲免费观看高清在线观看| 欧美一区激情视频在线观看| 欧美大片在线观看一区二区| 亚洲网在线观看| 欧美激情按摩| 亚洲欧洲日本国产| 美日韩精品视频免费看| 一区二区av在线| 欧美精品色网| 亚洲免费观看视频| 亚洲国产精品嫩草影院| 裸体一区二区| 亚洲日本电影| 亚洲美女少妇无套啪啪呻吟| 欧美gay视频激情| 日韩视频一区二区三区在线播放免费观看 | 欧美高清视频免费观看| 国产伪娘ts一区| 久久疯狂做爰流白浆xx| 亚洲欧美久久久久一区二区三区| 国产精品午夜国产小视频| 亚洲一区一卡| 久久精品国语| 亚洲一区美女视频在线观看免费| 中文欧美字幕免费| 国产主播精品在线| 激情久久久久久| 欧美成在线视频| 欧美日韩国产在线播放| 一本色道久久综合精品竹菊 | 亚洲香蕉在线观看| 国产欧美三级| 亚洲国产精品久久91精品| 欧美精品www| 欧美在线视频播放| 欧美激情精品久久久久久| 亚洲主播在线观看| 蜜臀久久99精品久久久久久9| 99综合在线| 欧美va天堂| 免费在线成人| 国产一区二区三区四区五区美女 | 亚洲综合视频一区| 艳妇臀荡乳欲伦亚洲一区| 欧美一区二区三区四区在线| 一区二区三区产品免费精品久久75| 亚洲美女毛片| 一区二区欧美日韩| 欧美激情精品久久久久久蜜臀 | 欧美日韩免费一区二区三区| 欧美激情精品久久久久久免费印度 | 你懂的国产精品| 正在播放亚洲| 亚洲一区二区在线观看视频| 欧美日韩精品一区视频| 日韩网站在线看片你懂的| 亚洲精品1区| 免费成人高清在线视频| 久久一区二区三区国产精品 | 欧美综合国产| 国内精品伊人久久久久av一坑| 午夜精品一区二区在线观看 | 久久免费的精品国产v∧| 久久一区二区三区国产精品| 亚洲电影下载| 黄色亚洲精品| 伊人伊人伊人久久| 在线欧美电影| 亚洲国产精品久久久久久女王| 国产精品一国产精品k频道56| 欧美激情一区二区久久久| 久久久久女教师免费一区| 午夜精品亚洲一区二区三区嫩草| 亚洲每日在线| 亚洲一区二区三区四区中文 | 亚洲欧美一级二级三级| 一区二区激情| 宅男精品导航| 欧美亚洲三区| 久久综合图片| 亚洲国产日韩欧美| 亚洲精品综合精品自拍| 99精品国产一区二区青青牛奶| 一区二区三区日韩精品视频| 夜夜嗨av一区二区三区四区| 久久久国产成人精品| 国内在线观看一区二区三区| 久久久噜噜噜久噜久久| 欧美在线观看一二区| 欧美成人午夜激情视频| 欧美日韩亚洲不卡| 国产一级揄自揄精品视频| 亚洲风情亚aⅴ在线发布| 亚洲视频图片小说| 久久精品91久久久久久再现| 老司机成人网| 亚洲欧美精品中文字幕在线| 久久综合色影院| 国产欧美精品| 一区二区三区成人精品| 久久久999精品视频| 亚洲精品久久| 久久婷婷成人综合色| 国产精品久久久久秋霞鲁丝| 亚洲国产精品99久久久久久久久| 亚洲网友自拍| 中文av字幕一区| 欧美韩日一区| 日韩视频一区二区| 欧美国产亚洲另类动漫| 久久成人免费网| 国产在线视频欧美一区二区三区| 中文亚洲免费| 亚洲午夜一区二区| 国产欧美欧美| 久久一二三区| 欧美国产日产韩国视频| 亚洲人成网站色ww在线| 男人的天堂亚洲| 欧美韩日高清| 久久gogo国模裸体人体| 久久久久久网| 亚洲一区二区三区在线观看视频| 亚洲黄色在线视频| 国产精品二区在线| 久久av红桃一区二区小说| 久久成人资源| 亚洲视频在线视频| 久久国产99| 欧美日韩国产高清视频| 欧美日韩亚洲高清| 欧美专区在线观看一区| 欧美成人a视频| 久久精品国产一区二区三| 蜜桃av噜噜一区| 久久国产精品99国产精| 欧美激情va永久在线播放| 久久精品一区二区三区四区| 欧美www视频| 久久久久国产精品www| 欧美日韩国产成人在线免费| 欧美一区在线看| 国产精品v欧美精品v日本精品动漫| 麻豆av一区二区三区久久| 国产精品欧美久久久久无广告| 免费视频最近日韩| 国产一区二区三区高清| 亚洲一区二区在线看| 一区二区三区高清视频在线观看| 久久国产福利国产秒拍| 篠田优中文在线播放第一区| 欧美日韩午夜| 中文国产一区| 午夜性色一区二区三区免费视频| 欧美国产日韩精品| 99成人在线| 欧美一级欧美一级在线播放| 欧美系列精品| 欧美与黑人午夜性猛交久久久| 久久久久久久国产| 91久久夜色精品国产九色|