向食人魔怪說嗨:與OGRE的第一類接觸

OGRE最近花費了大把的時間,努力地學習如何與 OGRE 這隻聲名遠播的巨獸成為好麻吉。至目前為止,總算是能夠稱得上稍微和它混熟了一點。關於 OGRE,這裡提出幾點我的學習筆記、目前觀察到的個性特質,以及與它相處的心得感想。

首先,對於稍具經驗的程式設計者來說,見到 OGRE 的第一眼印象,應該莫過於各種設計模式 (Design Pattern) 的廣泛使用了。在 OGRE 的架構設計與系統實作層面中,使用了 Abstract FactoryFactory MethodSingletonIteratorObserver 以及 Manager 等等許多著名的設計模式。說實在的,我還是頭一次看到這麼多不同種類的設計模式,能夠同時應用在一個遊戲繪圖引擎之中,正好能夠與以前所學的理論知識相互印證,學習起來非常爽快也很感動,真是令我大開眼界、大呼過癮!

而其中,最顯而易見的設計模式就是 SingletonManager 的結合使用。OGRE 利用這兩項模式的組合,製造出了一位一位各有擅場的「專業經理人」,使各個子系統所負的權責,都能夠劃分的非常清楚仔細。另外,利用 Observer 的概念,讓使用者能夠繼承 FrameListener 類別,自行定義進行繪圖程序前後的相關處理程序,也是一個非常優秀的設計模式應用實例。

回想自己當初剛進入業界時,在沒有任何人使用這些設計模式的情況下,額外看了許多書籍網站的資料,最後終於利用 Singleton 與 Manager 模式實作出幾項遊戲專案的子系統組件。結果深入認識了 OGRE 以後,才發現原來這些觀念已經如此廣泛地運用在遊戲引擎的設計架構之中。正所謂「他山之石,可以攻錯」,對於程式設計者來說,吸收新知以及學習別人的長處,的確是十分關鍵而不可或缺的能力啊。

如果以程式語言的角度觀察,OGRE 可以說是一個百分百純天然的 C++ 繪圖引擎。與其他多數的遊戲引擎與繪圖引擎不同,OGRE 身上沒有舊時代遺留下來的沈重包袱,或者為了從 C 語言轉換至 C++ 的「怪味道」等等過期的設計與實作方法。舉例來說,OGRE 對於 namepace 語法的全面使用,就是一個非常正確而且便利的作法:

namespace Ogre
{
    class SceneManager
    {
        // INSERT useful code here.
    };
}

從 C 語言時代逐漸演化琢磨而來的引擎前輩們,由於懼怕發生命名衝突 (Naming Confliction) 的問題,所以一般常見的作法,就是在原始碼的類別與結構名稱裡,加上一個自訂的前綴詞 (Prefix),形成 OgreSceneManager、OgreSceneNode、OgreRenderSystem 以及 OgreXXX 等等的類別名稱。只要如 OGRE 般善用 C++ 語言中的 namespace 語法,就能夠擺脫這些奇怪又累贅的前綴詞,更加能夠良好的切割類別名稱的定義空間。

而在 OGRE 複雜龐大的內心世界中,除了獨立運作的 Root 類別以外,其他的類別們主要可以分成場景管理資源管理以及繪圖系統三大類:

  • Scene Management:用來管理遊戲中的所有物件的外顯行為,相關的類別有 SceneManager、SceneNode、MovableObject 等等。
  • Resource Management:負責創建、分配與管理舉凡 Font、Mesh、Texture、Material 等等遊戲中與實體檔案相關的資訊,相關的類別有 ResourceManager、ArchiveManager、MaterialManager、TextureManager 等等。
  • Rendering:掌管繪圖程序的系統,相關的類別有 Renderable、RenderWindow、RenderSystem、RenderQueue 等等。

然而,如果 OGRE 中僅有這三項系統,其實難以滿足不同專案的不同需求,達到引擎本身應有的廣泛復用性與延展性。在不需要修改原始碼的前提之下,如何讓使用者達到最大的自由度,甚至能夠自由擴充原有的引擎功能?插件 (Plugin) 系統,就是 OGRE 給程式設計者的答案。有了場景、資源與繪圖系統三大基礎套件,再加上非常具有彈性的插件架構,就形成了 OGRE 之中最關鍵的黃金四角。而 OGRE 的心臟命脈,就在於萬能的 SceneManager 類別中!SceneManager 像是一座巨大的物件工廠,掌握了 OGRE 中多數物件與資源的生殺大權,能夠生產 SceneNode、Material、Light 以及 Animation 等等許多的類別物件並且加以管理。

如果有使用過其他商業遊戲引擎,或 Scene Graph 架構引擎的程式設計者,在初次與 OGRE 相識時,最難以適應的特點應該就是 Node 與 Object 分離而治的架構了。將 Scene Node 與 Scene Object 分離,是 OGRE 與其他繪圖引擎最大的不同點。剛開始使用的時候,需要花費不少時間重新調適使用習慣;而在習慣之後,就能夠發現這樣的架構不但擴充彈性較佳,在系統效能上也比傳統的 Scene Graph 架構有更為傑出的表現。

到此為止,聽起來 OGRE 似乎是個有百利而無一害的親切巨獸?然而,如同硬幣一樣,所有事物都有正反兩面的角度。

對於反面的第一眼觀察,我比較難以理解的是,為什麼 OGRE 明明是以 C++ 語言撰寫的引擎,卻要使用 Java 式的命名規則,使所有的成員函式名稱,都以首字字母小寫的形式存在,例如 getAnimation() 與 setAnimation() 而非 C++ 中常見的 GetAnimation() 與 SetAnimation() 形式。對於使用者來說,在配合自己所撰寫的程式碼時,需要特別注意命名慣例與撰寫風格上的統一。

另外,OGRE 對於例外處理 (Exception Handling) 機制的大量使用,令我產生不少使用上的疑慮。舉個例子來說,即使是在很尋常的 getAnimation() 函式中,只要使用者傳入了目前不存在其中的字串名稱,OGRE 就會立即拋出例外狀況:

String kAnimationName = "char_idle"; // 假設 char_idle 不存在於 mSceneMgr 中
Animation* pkAnim = mSceneMgr->getAnimation(kAnimationName); // 這裡會拋出例外狀況!
if (pkAnim == NULL) {
    // Create animation and/or report error
}

所以為了正確地取得 Animation 物件,必須要使用這樣的作法:

Animation* pkAnim = NULL;
String kAnimationName = "char_idle";
// 先檢查存在性(不會拋出例外狀況)
if (mSceneMgr->hasAnimation(kAnimationName)) {
    // 確認存在就可以取值
    pkAnim = mSceneMgr->getAnimation(kAnimationName);
}

原來可以直接檢查 getAnimation() 回傳值是否為 NULL 值的方式,在 OGRE 中需要多出一個檢查的步驟,對於許多程式設計者來說,可能一時也難以習慣這樣的作法。而在 OGRE 中處處可見、隨手可拋出的例外狀況的情境之下,很容易出現以下這樣非常糟糕的程式碼撰寫方式:

try {
    // Do something might throw exceptions!
    Animation* pkAnim = mSceneMgr->getAnimation(kAnimationName);
}
catch (...) {
    // 忽略,不做任何處理!
}

為了能夠順利創建出 Animation 物件,不產生例外狀況,程式設計者甚至會使用以下的作法:

Animation* pkAnim = NULL;
float fLength = 1.0f;

try {
    // 如果 kAnimationName 不存在,就會拋出例外而進入 catch 區塊
    pkAnim = mSceneMgr->getAnimation(kAnimationName);
}
catch (...) {
    // 在 catch 區塊中創建所需的 Animation 物件
    pkAnim = mSceneMgr->createAnimation(kAnimationName, fLength);
}

相信比較有經驗的程式設計者應該都知道,C++ Exception Handling 機制應當要使用在極少發生的「例外」狀況中,而不是用來取代所有可能合理發生的空值狀態。這樣的使用方法,我個人覺得很不恰當,除了對於程式執行效能上的衝擊以外,在程式設計者疏忽大意的情況下,更容易造成錯誤的程式碼撰寫習慣。如果,世界上只存在著兩種類型的程式設計者,其一是「贊同使用例外狀況處理」,其二是「反對使用例外狀況處理」的話,我應該是屬於「反對在 C++ 中使用例外狀況處理」的那一類。

而至目前為止,在與 OGRE 的相處過程中,我所遭遇到最重大的問題,就是資源物件名稱的唯一性。在 OGRE 的資源管理系統中,幾乎所有的資源物件都是以 string 型別的值做為索引鍵值,存放在 std::map 結構中。這種設計方法的優點,在於程式設計者能夠很有效率地檢查資源的存在性並且進行存取動作。問題是,資源管理系統完全不允許重複索引鍵值的物件產生。當程式設計者手動建立物件時,能夠輕易地避免鍵值重複的問題;然而,當資源物件是由實體檔案讀取進來的時候,只要載入同一個檔案兩次以上,OGRE 就會毫不留情地發出哀嚎聲,強制中斷程式系統的運作。

追根究底,原因在於目前的 OGRE 並不存在完善的資源物件 Clone 機制,這個缺陷對於欲建立大型遊戲專案的程式設計者來說,應該是一個十分頭痛難纏的問題;目前只能夠由引擎的使用者,在建立資源物件之前,自行傳入獨一無二並且保證絕不重複的 Unique String 值,以確保程式系統執行的正確性。最近在 OGRE 官網的論壇中,看到有人提出了這項資源索引鍵值衝突的問題,OGRE 作者的解決方案是利用一個 Callback 函式,讓使用者可以自訂遇到鍵值名稱衝突時的處理程序,相關的程式碼應該會於下個 OGRE 主要的版本更新中釋出。

最後,在文件方面,OGRE 官方的正式教學文件太過於貧瘠,SDK 中附上的 Manual 裡竟然只有寥寥可數的幾頁內容。反而是在官網 Wiki 上的教學文章內容比較豐富,也有許多 Step by Step 的主題教學與實際的程式碼範例,使初學者能夠學習到一個比較系統化的知識。值得安慰的是,OGRE 原始碼的註解內容撰寫得非常不錯!只要參考 API Reference 文件的說明,在單一類別的使用上就不會遭遇到太大的問題,同時也能夠自行下載原始碼回來,仔細地研究探索其中的實作細節。

至於在實體書籍方面,目前僅有 《Pro OGRE 3D Programming》 唯一一本。這本書在 OGRE 的基本概念與設計理念闡述,都有相當詳盡的介紹,可惜在進階的主題上著墨不深,但仍然是一本認識 OGRE 必讀的入門書籍。另外在中國地區,有許多遊戲都是使用 OGRE 開發完成的,因此對於 OGRE 的研究不少,在網路上也能夠找到非常多關於 OGRE 的簡體中文資訊。對於有志使用 OGRE 開發遊戲的程式設計者來說,多多瀏覽官方的 Forums 也是必不可少的例行工作。

總而言之,比起我之前曾經使用過的商業引擎,OGRE 可以說是一個設計架構很完善的新時代繪圖引擎,但是在許多使用層面上的細節,仍然有待更進一步的更新與加強。即使某些部分的功能還不夠完善,但就算是對於自行撰寫繪圖引擎的程式設計者來說,OGRE 也絕對是一個非常出色的參考典範。期待新的 OGRE 1.6 版本釋出以後,能有更具突破性的長足進步!

以上,是我目前對於 OGRE 的一點使用經驗與心得感想。如有其他想法,也歡迎提出討論~

25 Replies to “向食人魔怪說嗨:與OGRE的第一類接觸”

  1. Unique String的問題1.6似乎已經改掉了,
    寫得很棒 借我引用連結~~~

    半路:
    請用請用。 ^^

    感謝你的提醒~
    期待 1.6 版能夠加緊腳步趕快問世。 XD

  2. 台灣的遊戲業界也有專案使用 Ogre,例如先前宇奧的一款大富翁遊戲,以及我目前正在進行的專案也是。
    Naming Convention 的問題我覺得是還好,Java 傳統上對函式用小字首寫 (camelCase),但是 C++ 卻沒有所謂像文中所提到的大字首寫 (PascalCase) 傳統,主要是太多人學 C++ 都是從微軟的 MFC 或 .NET 開始學起,所以才會習慣於函式的 PascalCase 表示。我在 C++ 上見過太多不同的命名規範,Microsoft, boost, POCO, ACE, Ogre, CEGUI…etc, 各有各自的風格,如果專案同時用了多個第三方 library,往往容易混淆,這也是 C++ 經常為人詬病的一點,缺乏統一的命名規範。

    半路:
    原來台灣也有不少遊戲公司在使用 OGRE。
    不過,能夠找到的繁體中文資源,真的是少之又少啊。 Orz

    在 C++ 中的確有很多不同的命名規範,可能是我比較常見到 Pascal Case 的用法,也或者受到微軟的荼毒太深,所以自然而然習慣於函式名稱首字大寫的寫法。不過命名規範在 C# 中又不太一樣了哩。 XD

    很多程式設計者都有自己愛用的個人風格,在同時使用多個第三方函式庫的情況下,還真的是滿困擾的事情。 =_=

    感謝啦~ :P

  3. 我想會用try catch 想必是作者希望用的人把真正的工作以及錯誤處理,分隔開來吧
    如果沒有exception 那你的程式想必一堆if else 做一堆錯誤檢查的判斷
    這樣其他人想要看懂你的程式 要先過濾掉那ㄧ堆if else 的錯誤檢查 然後才是domain的邏輯
    如果善用exception 可以讓你try裡面的程式都是正規的domain邏輯 而catch 就是錯誤處理

    回頭來看例子 當你animation 找不到 你會有很多種處理方法
    可是正常的產品在跑 是不應該出現這種情況的 於是try裡面的程式就會很純粹的只剩下你要的domain邏輯
    而不是例外處理
    別人要了解 或是你幾個月後回頭來看你的程式 就可以很輕易的跳掉下面的錯誤處理
    這樣看code也會比較快喔

    這是我對exception的理解溜

    半路:
    嗯,你說得沒錯,Exception Handling 的確能夠免除繁複的錯誤檢查判斷,使程式碼變得比較簡單易懂。但是在 C++ 中使用 Exception 機制,實際上是會對程式效能造成影響的。如果能夠選擇,我還是會盡量不使用 Exception Handling,並且關閉專案中的選項。

    只是,使用 OGRE 的話就沒得選擇了。程式碼中與 try-catch-throw 的相關程式碼,還是需要特別留意撰寫,才不會造成更多的問題。如果是以 C# 撰寫的程式碼,我就會比較放心地使用 Exception 機制了。

    你的圖畫得好棒!很可愛耶~(眼睛一亮)
    我還是頭一次看到會畫畫的程式設計者。 :D

    謝謝你的回應~ ^^

  4. 效能的考慮上,是不是可以把”檢查”這個動作做成debug only feature?

    我們的引擎裡就有Dbg_if和Dbg_Assert,在製作遊戲的過程時方便大家找出錯誤的資源檔(沒圖檔啦、script變數不存在啦…),但這些檢查在release build裡都是會被忽視的,就想上面的Rich說的,在那個時候應該所有的資源都是正確的了。

    半路:
    利用 Preprocessor Macro 的方式,定義可切換的檢查程序嗎?
    這樣的方法的確很常見也很實用呢~

    不過在使用 try-catch 結構包覆程式碼的情況下,
    就會比較難發揮這種切換 Debug 與 Release 檢查程序的作法了。 Orz

  5. 遊戲程式大部份都在tight loop裡面, exception handling的overhead通常都可以感覺得到
    而且太倚賴exception也會讓程式變得比較不portable, 同樣的condition在不同的platform不一定都會throw exception, 即使有也未必是相同的exception
    所以一般來講我也是比較贊成使用debug assert的做法. 有錯誤就馬上給它死, 不要有任何急救的機會

    半路:
    聽你這麼一提,我才想到自己沒有在 PC 以外的平台使用過 Exception Handling 的經驗,所以也沒有遭遇過 Portability 的問題。除了效能問題以外,原來還有這方面的考量,以後使用 Exception 機制還是得多加留意才行。 = =+

    感謝你的分享。 ^^

  6. 拜讀過你的學習巨獸筆記之後,想請教您對於在Ogre上處理collision dected及collision response,有沒有比較好的建議,之前使用ogreode、ogrenewtown…等,覺得很麻煩不易使用,還有使用過ogreopcode,覺得很麻煩,尤其是在處理terrain的collision更是問題一堆,謝謝。

  7. @夢癡:
    你好,

    不知道你所需要的碰撞偵測處理程序,是要拿來做為什麼用途使用?如果只是單純要在地形上移動物體的話,應該使用 Ogre::RaySceneQuery 類別的功能就很足夠了。關於碰撞偵測,有一篇不錯的簡介「An Overview of Collision Detection in OGRE 3D」,可以參考看看。如果你的目標,是想要做出一些進階的物理引擎效果的話,那我就沒有接觸過了。

    請多多指教,謝謝。 ^^

  8. 半路
    你好,

    喔!謝謝,這篇我看過了,我的目標是要做到slide wall處理…等,RaySceneQuery 只能做Pick處理(貼地處理),3d動作遊戲是不太夠用了,目前我想可能以OgreNewton或NXOgre為主來當做Research的方向。順便問一下,ageia是不是就等於
    PhysX,謝謝。

  9. @夢癡:
    如果你要做的是具有真實物理反應的 3D 動作遊戲,那麼的確應該使用專門的物理引擎比較合適。

    國內還滿少看到有人在研究物理引擎的使用,我目前也沒有機會與時間接觸過這一類的引擎,期待你在研究與實做完成後,將心得成果分享出來~ :D

    PhysX 原來是 Ageia 公司的產品沒錯,不過現在已經被 NVIDIA 收購囉。

  10. 在今年八月底時,OGRE 官網中發起了一份使用者問卷調查,對於 OGRE 的使用用途、應用類型、經驗年限、團隊規模與組織規模進行統計。現在結果已經出爐了,可以在官網的討論區下載這份熱騰騰的 OGRE 2008 User Survey Report。報告中關於 OGRE 的用途:

    • 業餘愛好者及學生:60%
    • 商業用途:30%
    • 學術及政府使用者:10%

    這個數據對於 OSS Project 來說,算是一個很不錯的比例;而毫無意外地,其中又以遊戲專案的應用類型最多。另外比較特別的是,使用 OGRE 的團隊規模多在 5 人以下,組織規模也大多在 10 人以下,表示 OGRE 很受小型團隊的青睞。

  11. 您好:
    我是育達技術學院大三學生.
    我們的專題是做出一款遊戲.之前是用Brume.後來改換成XNA.
    我們的專題老師說我們下禮拜如果整合不出來個東東.就要我們換OGRE.
    但我們從沒碰過.想請問有沒有相關可以學習的?

    因為網路上看到的幾乎都是片段.學校也沒有書可以看…

    我們只剩下不到一個月的時間必須要做出一半的遊戲…

    謝謝

  12. @Cat:
    你好,

    如果你們沒有非常熟悉程式設計的話,我會比較建議使用 XNA 喔。

    因為 OGRE 實際上是一個「繪圖引擎」,如果要使用繪圖引擎完成一款遊戲作品,仍需要花費非常多的程式設計心力才有可能達成。而 XNA 則是屬於一個「遊戲框架」,天生就是拿來做為撰寫遊戲的用途。目前在市面上,有不少 XNA 相關的中文書籍,網路上也有許多簡體或繁體的中文網站資源可參考。

    不過,不論是使用 OGRE 或者 XNA,一樣都需要花費大量的時間在撰寫程式碼上喔。

  13. Ogre 有時也會咬你一口,如 Resource 不太支援 reload,Entity 和 Animation 的性能低下等等…

  14. 我在遊戲業工作時, 時常參考Ogre的source code, 學它的Architecture和API。
    我認為Ogre最大的致命傷在於效能,
    Ogre太過於依賴STL, 但常乎略STL容器的性值,
    例如用了vector後, 又狂加東西進去, 使得Ogre 裡XXXList都往往使用過超出它真正需要的記憶體。
    另外是Ogre的在不少方面所使用的演算法也不過好。
    如果有人用Ogre做出了一個MMORPG, 那一定是個又慢記憶體又吃超兇的怪獸。

    而Ogre最令人激賞是它的API設計,
    完全follow OOP的精神, class切得細, 功能明確簡單, 很難看到一個class有上數十個member function,
    而且object的ownership定義的很明確,
    使業餘人士可以很快的掌握它的精神和使用它, 並且開發出小型作品。
    當我是學生時, 只花了一個月就可以使用自如, 比起在業界經驗, Ogre的架構實在值得業界學習。

  15. @Alvin:
    很同意你的見解!

    在架構設計上,OGRE 真的有很值得學習之處,缺點也如同你所提的,過度使用 STL 容器以及低階演算法效能不佳等等。我想,以可用於商業化遊戲的免費資源來說,OGRE 已算是目前最完善也最活躍的繪圖引擎了。

    我認為 OGRE 整體的設計理念與系統架構相當正確。做為一個開源專案,OGRE 的目標是先建構出精巧又可擴充的引擎設計架構,之後再逐步修改細節與底層的部分。當然,OGRE 的未來還有很大的進步空間、很長的路要走,就看開源社群和專案主導者 sinbad 的作為了。

    國外有個使用 OGRE 的 MMORPG 正在開發中,大概要 18 至 24 個月後才會上市,我很期待那款遊戲作品的表現~ ^^

  16. 這段時間在看ogre的source,发现资源管理这部分写的特别复杂。
    不知道这样做有什么好处。
    麻烦版主有空能在多介绍一些ogre架构的文章。
    网上找了好久也没有太好的这方面的文章

  17. @nichole:
    很久一段時間沒有繼續學習 OGRE 了,所以目前在這方面,我可能沒辦法提供什麼有用的教學資訊。就我之前的印象所及,OGRE 的資源系統有一些 pitfall 存在,我會建議你深入源碼去剖析相關 API 的內部構造,才不會產生誤用資源系統的可能性。

  18. 第一次看到本文,寫的很不錯。但對於文中提到的:
    “所以為了正確地取得 Animation 物件,必須要使用這樣的作法:

    view plaincopy to clipboardprint?
    Animation* pkAnim = NULL;
    String kAnimationName = “char_idle”;
    // 先檢查存在性(不會拋出例外狀況)
    if (mSceneMgr->hasAnimation(kAnimationName)) {
    // 確認存在就可以取值
    pkAnim = mSceneMgr->getAnimation(kAnimationName);
    }

    Animation* pkAnim = NULL;
    String kAnimationName = “char_idle”;
    // 先檢查存在性(不會拋出例外狀況)
    if (mSceneMgr->hasAnimation(kAnimationName)) {
    // 確認存在就可以取值
    pkAnim = mSceneMgr->getAnimation(kAnimationName);
    }
    原來可以直接檢查 getAnimation() 回傳值是否為 NULL 值的方式,在 OGRE 中需要多出一個檢查的步驟,對於許多程式設計者來說,可能一時也難以習慣這樣的作法。”

    我有不同的看法,其實OO中有個這樣的習慣或是說UC的約定,功能執行者不負責檢查前置條件是否成立,UC中,前置條件是功能正常執行的最小保證,應該由呼叫者來保證前置條件的正確性。在您說的這個例子中,getAnimation本身是類的一個public公開方法也就是說是一個對象提供的一個功能執行者,那麼的確不該在內部來檢查參數的正確性。但如果getAnimation是private或是protected的話,那麼他的參數就不是前置條件,在UC中應該定義為“約束”,“約束”也可以是參數,這時,約束便可以在內部作檢測,因為被命名為private或protected的目的就是不想在類外部來暴露這個操作,換言之,它就不是一個對象提供的一個功能執行者。

    上面是在下的一點愚見。

  19. @邪恶代码:
    你好,

    很有道理,的確在一個正確的物件導向設計的模組中,功能執行者不應負責檢查前置條件合法與否,我想這一點,或許也是 OGRE 作者設計出這種使用方法的本意吧!

    但從另一個角度來看,就現實層面來說,程式設計者可是以懶惰著稱的傢伙(我自己也是),許多人並不會嚴謹地遵循物件導向設計的思維理念,所以若要將前置條件交由模組的使用者自行檢查的話,仍然會產生一定的風險,不可不慎哪。

    感謝你提供的設計思維! :)

  20. 現在再回來看一次這篇文章,OGRE已經不是那麼完美了,現在又大又肥,相容於舊時代的Rendering pipeline讓整體結構有那麼一點不是很乾淨的感覺在。

  21. @Bric:
    我很久沒關注 OGRE 的近況了,但聽到你這麼說還真是遺憾哪。在開源繪圖引擎的領域中,OGRE 可以說是一顆最閃亮的星星,希望它可別墜落了。

  22. Hi,半路大
    我最近在研究Ogre的動畫部分,目前知道Ogre提供兩種方式可以去做動畫
    一種是透過3D建模軟體,如Blender、3D Max直接做好動畫再透過Ogre Export匯出Skeleton格式檔案給Ogre使用

    另一種是可以用寫Code的方式產生動畫,透過sceneManager->createAnimation ()來產生動畫
    但是似乎只提供三種method
    void Ogre::KeyFrame::setTranslate ( const Vector3 & trans )
    void Ogre::KeyFrame::setScale ( const Vector3 & scale )
    void Ogre::KeyFrame::setRotation ( const Quaternion & rot )
    變成需要在每一個時間軸上指定位置
    TransformKeyFrame* key;

    key = track->createNodeKeyFrame(0.0f);
    key->setTranslate(Vector3(-x, -y,z));
    key->setScale(Vector3(s,s,s));
    譬如我把某個物件呈現如fade-in/out、非等速度的漸變移動動畫等
    類似像android有tween animation的效果的話,有辦法做到嗎?

    因為看了Ogre官方的API似乎對於animation方面操作的API提供的很少
    不曉得半路大有使用程式碼去撰寫動畫的經驗嗎?
    或是有沒有3D animation的library可以提供在Ogre去使用。

    不好意思,問了這麼多問題,
    麻煩你了。

Leave a Reply