與Ogre共舞:第二步,Hello, Ogre! 讓Ogre動起來
安裝與設定完成後,一定迫不及待的想開始玩點什麼。Ogre準備了許多的範例程式,涵蓋了不少3D效果與描繪技巧,仔細研讀範例程式會是個好的開始。但是,如果你和我一樣,不只是想改改範例的code就好,那就讓我們手動打造Ogre的世界吧!以下範例的形式,偏向「只由程式碼」讓Ogre工作,不使用Ogre的設定檔與提供的資源。
在說明之前,先談談Ogre這個3D繪圖引擎的設計。Ogre主要由Root與三大子系統組成,分別是
- Render Systems – 負責Ogre繪圖與底層描繪硬體API(OpenGL, Direct3D)之間的溝通。
- Scene Management – 負責管理3D物件的場景,例如物件的類型、位置、姿態等等。
- Resource Management – 負責3D場景中相關的資源,包括模型、材質、字型等等。這些資源通常以檔案形式存在,因此也包含了相對應的載入、分配等管理。
Root物件可以說代表了Ogre的一切。一旦Root物件被建立,Ogre就算是被啟動。反之,當Root物件被消滅,Ogre也就完全結束了。Root管理所有其他的子系統,提供存取方式,負責取得RenderSystem與創建SceneManager等等。在這個”Hello, Ogre!”例子中,先只看Root跟RenderSystem的關係,建立一個單純的Ogre視窗。
// start the Ogre application
Root *root = new Root( "", "" );
產生一個Ogre的應用程式,一定從建立Root物件開始。這裡要注意的是,Root物件建構時的參數,第一個預設是”plugins.cfg”,第二個是”ogre.cfg”。如果不想使用設定檔(也就是純手動方式)建立Ogre的話,Root建構子的參數必須按照上面的寫法。若忽略參數(i.e. new Root(); ),則會自動載入”plugins.cfg”與”ogre.cfg”。
那,plugins.cfg是做什麼的呢?plugins.cfg裡條列了Ogre預備載入的plug-in,包含最重要的RenderSystem plugin。如果用上面的寫法,因為不使用plugin.cfg,Ogre不會為你載入RenderSystem,你必須自己動手載入並加以設定。因此,第二步就是載入RenderSystem的plugin。
// load a plugin(DLL) of the render system #ifdef _DEBUG root->loadPlugin( "RenderSystem_Direct3D9_d" ); // for a debug build #else root->loadPlugin( "RenderSystem_Direct3D9" ); // for a release build #endif
Ogre的plugin是以dll檔形式(在Windows下,若在linux下則是.so)存在,使用Root::loadPlugin()方法手動載入,副檔名可以不要填寫。這裡以Windows下使用Direct3D為例,所以只載入Direct3D的plugin。同時,上述的寫法會自動依照編譯的組態,選擇適當組態編譯出來的dll,以避免程式崩潰。若想使用OpenGL的plugin,仿照上面的方式即可。當然,也可以同時載入Direct3D與OpenGL兩個RenderSystem的plugin,由使用者選擇適當的RenderSystem。
載入RenderSystem的plugin後,就是要設定Root要使用的RenderSystem:
// select the Direct3D renderer
RenderSystemList *render_sys_list = root->getAvailableRenderers();
RenderSystemList::iterator it_rs( render_sys_list->begin() );
while ( it_rs != render_sys_list->end() )
{
RenderSystem *render_sys = *(it_rs++);
if ( render_sys->getName().find( "Direct3D9" ) != String::npos )
{
root->setRenderSystem( render_sys );
break;
}
}
先利用Root::getAvailableRenderers()取得所有載入的RenderSystem,這些資訊會存放在RenderSystemList型態的變數中。接著,以一個迭代器(iterator)走訪所有的RendrSystem,在這裡設定選用”Direct3D9″作為RenderSystem。上面第8行,如果在RenderSystem的名稱中找到”Direct3D9″,則以Root::setRenderSystem()設定欲使用的RenderSystem,到這裡,Root跟RenderSystem之間的關係已經建立完成了。要注意的是,如果整個while迴圈跑完,都還沒有任何的RenderSystem被指定的話,Ogre是玩不下去的!有道是:流汗總比流血好,自己結束總比當掉好,下面這段保險還是補一下吧。
// end gracelessly if the preferred renderer is not available
if ( root->getRenderSystem() == NULL )
{
delete root;
return -1;
}
該有的都有了以後,該讓Root進行初始化的動作。3D繪圖最重要的是什麼?當然是那個視窗啊!所以,利用Root::initialise()幫我們初始化剛剛選好的RenderSystem。
// initialize the root, and tell the root NOT to create a render window
root->initialise( false );
慢著,那個false跟註解是怎麼回事?喔,因為Root::initialise()本來會自動幫我們產生一個視窗的,但這樣就不「手動」了。使用參數false,就必須自己產生一個視窗。也不難,Root也準備了建立視窗的指令,手動來建立一個視窗看看:
// manually create a render window
root->createRenderWindow( "Hello, Ogre!", // window title
320, // window (client area) width
240, // window height
false ); // full screen mode
如何,簡單明瞭吧!建立一個320*240大小(繪圖區)的視窗,採用視窗模式,視窗標題是”Hello, Ogre!”。到這裡,應該就可以看到一個視窗跑出來了。別急著開始執行,還有個重要的東東:
// start the rendering loop
root->startRendering();
這行敘述啟動了Ogre的自動繪圖迴圈,所有描繪場景的動作,都會持續的在這個迴圈中不斷的執行。除非描繪的流程被中斷,不然不會從該敘述返回。在這個例子中,還沒有辦法終止這個描繪的流程,要一直等到加入FrameListener後,才會有解。不過也別灰心,至少,現在可以看到一個Ogre的視窗,有著”Hello, Ogre!”的標題。什麼?你說怎麼黑黑的沒東西顯示?當然啊,這是”Hello, Ogre!”嘛…

[下載] 範例程式 (VC2008 專案)
ogre_tutorial_2.zip 2.7 Kb
看了您的教程,写得非常不错。
我是一个正在学习OGRE的程序员,希望能和你交流一下
教程中的代码,无法下载,可能是中国网络的原因吧。
如果可以的话希望您能另外发布一下贵教程的代码(mediafire在大陆是不能登入的)或者直接发至我的邮箱。
万分感谢
Comment 由 天天 | 五月 5, 2009
謝謝你對這個教學有興趣。mediafire無法被大陸地區的網友使用,實在是很糟的事,我已經將目前所有的範例附件過去了,希望對你有幫助!
Comment 由 chia0418 | 五月 5, 2009
你好,我是一个中国女孩 现在在俄罗斯留学 一直我都对视景仿真 编写游戏很有兴趣 也自学过一些opengl 现在在看ogre 有些问题 如果您方便的话 希望可以给我一些学习上的建议(还有些问题想请教您)
可以的话请回复我的邮件 谢谢
Comment 由 yang | 五月 6, 2009