文獻來源網址:http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Basic+Tutorial+1&structure=Tutorials
導言:
在本節教程中,我們將會向您介紹OGRE最基本的組成結構:場景管理器(SceneManager),場景節點(SceneNode)和實體對象(Entity objects),我們不會涉及大量的源代碼,相反地,由於開始學習OGRE,我們會着重給你介紹幾本概念。
當您瀏覽本教程的時候,你可以慢慢地將代碼加入到你自己的項目,然後查看編譯結果。沒有比實際編程更好的方法去熟悉這些概念,如果你僅僅是閱讀,我勸你還是打住你的念頭吧。(個人注:實踐是學習編程最好的方法)
預備知識:
1,本教程假設你已經擁有C++知識和能夠建立和編譯OGRE運用程序
2,本教程假設你已經用 Ogre Wiki Tutorial Framework創建了一個工程,或者,手動地,用CMake或者Ogre運用程序嚮導--請查看Setting Up An Application 使用說明
開始:
從這裏開始在這篇教程裏,我們將使用已經寫好的代碼作爲模版。除了我們將要在createScene函數裏面添加的代碼之外,您可以暫時忽略其他的東西。在後面的教程裏我會深入講解OGRE程序是如何工作的,現在我們只需要從最簡單的地方學起就行了。在您的IDE創建一個名叫Tutorial工程,然後把教程運用程序框架(tutorial application framework)下面的代碼添加進去:
BaseApplication.h BaseApplication.cpp TutorialApplication.h TutorialApplication.cpp
從這裏獲取以上文件: Ogre Wiki Tutorial Framework
或者,使用Ogre AppWizard.
TutorialApplication.cpp是本教程中我們唯一使用的文件,並且我們只在成員函數createScene()進行工作。
TutorialApplication.cpp應當包含以下代碼
#include "TutorialApplication.h"
TutorialApplication::TutorialApplication(void)
{
}
TutorialApplication::~TutorialApplication(void)
{
}
//-------------------------------------------------------------------------------------
void TutorialApplication::createScene(void)
{
// Set the scene's ambient light
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));
// Create an Entity
Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");
// Create a SceneNode and attach the Entity to it
Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("HeadNode");
headNode->attachObject(ogreHead);
// Create a Light and set its position
Ogre::Light* light = mSceneMgr->createLight("MainLight");
light->setPosition(20.0f, 80.0f, 50.0f);
}
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char *argv[])
#endif
{
// Create application object
TutorialApplication app;
try
{
app.go();
} catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR| MB_TASKMODAL);
#else
std::cerr << "An exception has occured: " << e.getFullDescription().c_str() << std::endl;
#endif
}
return 0;
}
#ifdef __cplusplus
}
#endif
繼續編譯和運行這個程序,當然你要保證你的環境配置正確的,一旦你的程序是正常運行起來,使用WASD鍵移動,鼠標鍵用來環顧四周,ESC鍵退出程序。
個人注:在IDE中創建工程時,可以選擇控制檯,也可以選擇win32。
小細節:上面可以看出,average fps 有個fps重疊的字符串fps,這應該是個bug,修改文件SdkTray.h,將2768行與2774行中的 values.push_back(s); 改爲values.push_back(str);修改後運行的截圖:多出來的fps字符串沒有了,感覺清爽多了,
解決問題:
如果你有問題,請檢查下運用程序的設置使你的編譯器配置正確,或者查看Ogre.log文件獲取更多的詳細信息。如果你需要幫助。可以去搜索論壇(http://www.ogre3d.org/forums/search.php),可能你的問題,別人已經遇到了很多次。如果這是一個新的問題,閱讀論壇規則,然後再問。確保從您的Ogre.log提供相關細節,異常,錯誤消息,和/或調試後的痕跡。
需要注意的是以後的教程中,將不包含此類問題解決的信息,所以請如果您有問題,要特別注意以下幾個部分。
1,MessageBox的問題
如果你使用支持UNICODE字符集的VS,你可能會遇到如下問題:
error C2664: 'MessageBoxW' : cannot convert parameter 2 from 'const char *' to 'LPCWSTR' Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
這個問題是MessageBox函數(在這種情況下)是期待的是Unicode類型的字符串(個人注:此時的形參的類型必須是寬字符類型的),而我們給的是你ANSI字符串,修正這個錯誤,我們只需要修改下面的代碼
MessageBox( NULL, e.what(), "An exception has occurred!", MB_OK | MB_IConerror | MB_TASKMODAL);
爲:
MessageBoxA( NULL, e.what(), "An exception has occurred!", MB_OK | MB_IConerror | MB_TASKMODAL);
或者,你也可以將編譯器的字符集從Unicode改爲ANSI,然後,你這樣做,會失去國際語言的支持。
這樣做的原因是,"MessageBox "將被自動解析爲,要麼是MessageBoxA(ANSI),要麼是MessageBoxW(寬/ Unicode),根據項目配置,我們明確它使用ANSI修復該錯誤。
2,缺失配置文件或者dll
如果你試圖啓動你剛生成的應用程序,但該程序報錯,缺少DLL或配置文件(*.cfg),,那麼你可能沒有將它們從OgreSDK的文件夾中複製過來,在VS中,當你在release模式下編譯你的運用程序,它將release版的可執行文件放在[ProjectFolder]\ BIN \ release文件夾中,debug版的可執行文件放在[ProjectFolder] \ BIN \ debug文件夾中。你必須從OgreSDK中複製所有的".dll",".cfg" 的文件到相應的文件夾中。也就是說,將這些文件從[OgreSDK]\ BIN \release 文件夾複製到[ProjectFolder]\ BIN\release文件夾,從[OgreSDK] \ BIN \debug文件夾複製到[ProjectFolder] \ BIN \debug文件夾。您還需要編輯的resources.cfg文件以便指向正確的路徑。想獲取更多信息,請參閱下一節。
3,資源或插件問題
確保你有一個plugins.cfg和resources.cfg文件在與可執行文件相同的目錄中。Plugins.cfg告訴OGRE哪個渲染庫是可用的(Direct3D9,OpenGL等)。resources.cfg被ExampleApplication使用,用於指定紋理,網格模型和腳本的路徑。它們兩個都是文本文件,所以可以編輯它們以保證這些路徑是正確的。否則,您的OGRE設置對話框可能沒有任何渲染庫,或者您可能會收到一個錯誤,在你的屏幕上或在Ogre.log文件中,看起來像這樣:
Description: ../../Media/packs/OgreCore.zip - error whilst opening archive: Unable to read zip file
如果是這種情況,打開你的resources.cfg文件,修改它包含的路徑,使它指向Media文件夾(附帶有食人魔(Ogre))的位置。注意:您不能使用環境變量在這些路徑上,例如$(SomeVariable)。
ogre是怎麼工作的?
OGRE是怎樣工作的這是一個很廣的話題,我們將從場景管理器開始然後進一步瞭解場景節點和實體。這三個類是所有OGRE程序的基石。
1,場景管理器基礎:
在屏幕上顯示的所有東西都是由場景管理器來管理。當您在場景中添加物體時,場景管理器會記錄這些物體的位置。當您添加攝像機來觀看某個場景時,場景管理器會記錄攝像機的位置。當您添加平面、廣告牌、燈光時,場景管理器同樣會管理他們。 OGRE裏有很多種場景管理器。有的場景管理器渲染地面,有的場景管理器渲染BSP表等等。在後面,我們將進一步瞭解場景管理器。
2,實體基礎:
一個實體是可以在場景中渲染的物體之一。您可以把實體理解爲任何一個3D模型。一個機器人可以是一個實體,一條魚可以是一個實體,大地草原可以是一個非常大的實體。燈光,攝像機,粒子,廣告牌等不能成爲實體。
關於OGRE需要注意的一點是,它從對象的位置和方向分離出渲染對象,這就意味着,在 Ogre中你不能夠直接將一個實體放入到場景中,而是將實體與場景節點綁在一起,這個場景節點則包括了實體的方位信息。
3,場景節點基礎:
場景節點將持續跟蹤與它綁在一起的實體的方位。當你創建了一個實體時,它直到與一個場景節點綁定後纔會被渲染。同樣,一個場景節點也不能單獨的在屏幕上顯示出來,只有與一個實體綁定後才能在屏幕上顯示。
場景節點可以綁定多個實體。例如在屏幕上有在行走的一個人物對象,並且希望這個對象產生髮光效果,要實現這些,首先你需要創建一個場景節點,然後再創建一個人物對象的實體並與場景節點綁定在一起,之後你還需要創建一個光照模型也與這個場景節點綁定在一起。場景節點同樣可以與其它場景節點綁定以描述更完整的對象。我們在後續的章節中介紹場景節點更多的用法。
在場景中,場景節點的位置總是與它的父節點相關。每一個場景管理器都包含一個根節點。
你的第一個OGRE程序
返回到我們剛纔創建的代碼,找到 TutorialApplication::createScene成員函數。首先需要爲整個場景設置環境光,這樣纔可以看到要顯示的內容,通過調用setAmbientLight函數並指定環境光的顏色就可以做到這些。指定的顏色由紅、綠、藍三種顏色組成,且每種色數值範圍在0到1之間。將下一句添加到 createScene 中:
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));
下一步創建一個 Entity,通過調用 SceneManager的 createEntity 方法來創建:
Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");
好的,一些問題需要提出來,首先,mSceneMgr來自哪裏?我們調用函數的參數是什麼?mSceneMgr變量是當前場景管理器對象(這個是BaseApplication類爲我們做的)。createEntity函數的第一個參數是我們創建實體對象的名字,所有的實體必須有唯一的名字,如果你創建兩個名字相同的實體對象,你會得到一個錯誤,第二個參數 "ogrehead.mesh" 指明我們用於實體的網格模型,"ogrehead.mesh"是一個來自Ogre SDK的資源。資源加載和網格模型將會在後面的教程中涉及,現在,我們直接使用具有資源加載能力的BaseApplication類。我們已經創建了一個實體,但還需要創建一個場景節點來與它綁定在一起。既然每個場景管理器都有一個根節點,那我們就在根節點下創建一個場景節點。
Ogre::SceneNode* headNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("HeadNode");
這句代碼首先調用場景管理器的 getRootSceneNode方法來獲取根節點,再使用根節點的 createChildSceneNode方法創建一個名爲"HeadNode"的場景節點。與實體一樣,場景節點的名字也是唯一的。
然後,將實體綁定到場景節點,指定了Ogre Head渲染位置
headNode->attachObject(ogreHead);
儘管燈光知道下一個章節纔會涉及,但是,我們在這裏添加一個燈光,這樣我們看到模型帶有適當的陰影,而不是來自自然光的平坦陰影,當我們創建燈光時,我們也要給一個唯一的名字。
Ogre::Light* light = mSceneMgr->createLight( "MainLight" );
一旦燈光被創建,可以用setPosition函數設置它的位置,。給定的這三個參數是要設置的新的位置的X,Y和Z座標。座標將在下面詳細討論。
light->setPosition(20, 80, 50);
編譯運行你的程序,你將會在屏幕中看到食人魔的頭像。
座標與向量
待續.....