OGRE資源相關分析
Resource
Resource的類繼承體系如下:
Resource代表着一類可以被載入的資源,比如Mesh,Texture等。每個資源有其唯一的Name,根據Name可以定位到某個資源,這樣也確保了資源只能被載入一次。並且Resource必須在一段時間不使用的時候要被刪除。
要實現爲Resource子類有以下要求:
1. 構造函數和Resorce有相同的參數。子類構造函數不允許有其它的參數傳入,如果需要設置其它成員變量可以通過Set函數。
2.實現Resource中的純虛函數loadImpl和unloadImpl。而且mSize必須在loadImpl調用後設置。
3. StringInterface ParamCommand and ParamDictionary setups in order to allow setting of core parameters (prior to load)through a generic interface.
資源有兩種載入的方法,一個是通過解析腳本文件自動載入,另一種是手工載入。手工載入的好處是:由於某些意外原因導致資源unload,這時就不能通過Resource的reload重新載入,因爲是意外原因所以mIsLoaded就仍然爲true。通過使用手工載入就可以預防這個問題。
ResourceManager
ResourceManager的類繼承體系如下:
和Resource對比我們可以得出ResourceManager和Resource是一一對應的。其實一個具體類型的ResourceManager就是管理管理這個類型資源的資源池。通過ResourceManager可以可以索引這些資源,查找資源,載入和銷燬資源。
ResourceManager還有一些其它功能,比如它保存着它所掌管類型的資源的載入,卸載優先順序。這樣載入資源的時候可以一種一種的載入,節省了時間。ResourceManager自己定義了內存預算,我們載入/卸載的時候都會通知該變這個內存預算值,這樣我們就可以得知我們使用了多少內存。另外,要注意的一點是資源可以通過Resource類被載入和卸載,但只能使用ResourceManager來創建和刪除。
ResourceGroupManager
與這個類聲明所在的.h文件中有一個ResourceGroupListener類的聲明,這個類定義瞭如下幾種事件接口,它們在操作資源的不同時候被調用。
· resourceGroupScriptingStarted
· scriptParseStarted (*)
· scriptParseEnded (*)
· resourceGroupScriptingEnded
· resourceGroupLoadStarted
· resourceLoadStarted (*)
· resourceLoadEnded (*)
· worldGeometryStageStarted (*)
· worldGeometryStageEnded (*)
· resourceGroupLoadEnded
ResourceGroupManager把資源分成一個個的組,通過調用資源對應的ResourceManager(注:通過ResourceManagerMap使得string sourceType和ResourceManager掛鉤)來加載或卸載組中的資源。此外如果一個ResourceManager支持通過腳本來定義資源,那麼這個類就會找到腳本的位置然後告訴ResourceManager來解析它們。在ResourceGroupManager中,資源可以看成有4種狀態:Undefined,Declared,Unloaded,Loaded。
ResourceGroupManager可以讓你把一系列資源看成是一個單元來載入和卸載。比如一個資源組可以是遊戲中一個關卡的所有資源。OGRE中有一個預先定義的資源組: DEFAULT_RESOURCE_GROUP_NAME,它所控制的資源只有到了程序退出時纔會被釋放。
一旦你創建了自己的資源組,你可以通過以下3種途徑爲這個資源組載入資源:
1. 調用declareResource()。
2. 通過使用腳本;ResourceManager的一些子類型擁有特定的腳本類型比如:.material,.overlay等。
3. 調用ResourceManager::create。
如果你使用前面兩種方法必須確保調用initialiseResourceGroup。
通過 void createResourceGroup(const String& name)方法我們可以創建一個資源組。
創建好一個資源組後我們就可以爲這個資源組增加搜索路徑,我們將在這些路徑中查找我們需要的資源。通過以下函數我們可以爲一個資源組添加搜索路徑:
void ResourceGroupManager::addResourceLocation(const String& name,
const String& locType,const String& resGroup,bool recursive)
|
設置好資源路徑後我們就可以爲資源組聲明資源,從而你可以載入和卸載它們。聲明資源也可以通過解析腳本文件。
void declareResource(const String& name, const String& resourceType,
const String& groupName = DEFAULT_RESOURCE_GROUP_NAME,
const NameValuePairList& loadParameters = NameValuePairList());
|
當我們創建資源組後,添加了搜索路徑,並且可能也聲明瞭一些資源後,我們還不能直接使用資源,這個時候我們要調用void initialiseResourceGroup(const String& name)來初始化資源組。這個方法也觸發了以下兩個行爲:
1. 通過給定的資源路徑解析資源路徑中所有類型資源的腳本,腳本里面的資源將被創建,但這個時候還沒有被載入。
2. 創建通過調用declareResource聲明的資源。同樣這個時候資源也僅僅是被創建而沒有被載入。
所以這個方法只是爲各個ResourceManager創建資源而沒有載入它們。僅僅是表面應用程序可以找到這些資源,但在調用load之前還不能被使用。還有就是一旦調用這個方法後你就無法再通過腳本,和提前聲明來創建新的資源。如果要那麼做只有先調用clearResourceGroup,然後重新聲明資源,再調用這個函數。
資源創建好後爲了使用我們必須調用
void loadResourceGroup(const String& name, bool loadMainResources = true,
bool loadWorldGeom = true);
這樣我們纔可以使用這些資源。
與它相對的是void unloadResourceGroup(const String& name)調用這個函數後資源將被卸載,但是資源的聲明仍然存在於各個ResourceManager中。要取消所有的聲明必須調用
void clearResourceGroup(const String& name),當這個函數被調用後所有資源的聲明也就不存在了,只剩下資源的搜索路徑。
下面這個方法最徹底,它先卸載資源,然後清空資源,最後把資源組從資源組的集合中刪除。
void destroyResourceGroup(const String& name)
[demo分析]
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// 執行應用程序初始化:
Root * ogreRoot=new Root();
// 顯示配置窗口
bool rtn = g_ogreRoot->showConfigDialog();
// 如果配置文件已經存在(已經執行過起碼一次 showConfigDialog ),
// 那麼你可以用下面這句之間讀取配置,而不需要顯示配置窗口。
// g_ogreRoot->restoreConfig();
// 創建渲染窗口
g_ogreRoot->initialise(true, "My Render Window"); // 這裏的 true 指示 ogre 自動創建窗口
RenderWindow * renderWindow =g_ogreRoot->getAutoCreatedWindow();
renderWindow->setAutoUpdated(true);
// 創建場景管理器,這個TerrainSceneManager 是指地形場景管理器
SceneManager* mSceneMgr = g_ogreRoot->createSceneManager("TerrainSceneManager");
// 創建攝像機
Camera* mCamera = mSceneMgr->createCamera("PlayerCam");
mCamera->setPosition(Vector3(0,0,-300)); // 攝像機位置
mCamera->lookAt(Vector3(0,0,800)); // 攝像機朝向
// 設置渲染窗口的視口(和我們的攝像機綁定)
Viewport *vp = renderWindow->addViewport(mCamera);
vp->setBackgroundColour(ColourValue(0, 0, 0));
// 定義資源的讀取目錄/文件,dragon.zip 放在執行目錄,這個文件可以在 OgreSDK/media/packs 目錄下找到
ResourceGroupManager::getSingleton().addResourceLocation(
"dragon.zip", "Zip", "General"
);
// 我把 script 目錄從 OgreSDK/media/materials/scripts 複製到執行目錄下了,龍的皮膚着色需要用到某個腳本
ResourceGroupManager::getSingleton().addResourceLocation(
"scripts", "FileSystem", "General"
);
// 初始化資源管理器
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
// 讀取龍的模型
Entity * ent = mSceneMgr->createEntity("dragon", "dragon.mesh");
// 把模型放入場景管理器
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(ent);
// 開始渲染
g_ogreRoot->startRendering();
return 0;
};
把 OgreSDK/bin/release 下的文件都複製到執行目錄,然後試試吧!
好了,這樣我們的第一個 ogre 程序就寫好了,很簡單吧。當初寫的時候碰到不少問題,主要是文件找不到,資源找不到……
|
OGRE 啓動詳解 + 實體的加載與顯示
#include "stdafx.h"
#ifdef _DEBUG
#pragma comment(lib,"ogremain_d.lib")
#else
#pragma comment(lib,"ogremain.lib")
#endif
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
{
using namespace Ogre;
try
{
/**//// Root的構造函數裏會創建所有Factory以及Manager
/// 這裏的3個參數,都是可以爲空的(不是省略).
/// 第1個參數指明瞭插件配置的文件名. 這個文件裏指明瞭我們將要使用的圖形驅動(DX or GL)等DLL.
/// 既然是圖形程序,所以肯定要有圖形驅動了,如果這個參數爲空,那麼我們必須手動去加載圖形驅動.
/// 第2個參數指明瞭OGRE的圖形驅動配置文件。
/// 這個參數實際上是在調試的時候使用的,發佈版本的時候肯定是不要它的.
/// 它在Root裏的ShowDialg裏使用,用來動態的配置當前要使用的圖形驅動.
/// 如果我們可以確定我們要使用的圖形驅動,完全可以配置我們自己的圖形驅動. 具體代碼可以參考下面.
/// 第3個參數指定了我們要使用的LOG文件名
Root * root = new Root("",
"",
"");
/**//// 我們手動加載圖形驅動
#ifdef _DEBUG
root->loadPlugin("Plugins/RenderSystem_Direct3D9_d");
#else
root->loadPlugin("Plugins/RenderSystem_Direct3D9");
#endif
/**//// 由於OGRE的資源加載都由ResourceGroupManager來管理,不通過WINDOWS直接管理.
/// 所以,要正常使用OGRE的資源加載,我們還得把我們的資源目錄給加到這個Manager裏去.
/// 說白了,就是資源的環境路徑.
/// 最起碼,當前目錄是要加的吧 ^_^
/// 這裏也有3個參數。
/// 第1個參數指明瞭我們要加入的資源的相對目錄名
/// 第2個參數指明瞭我們要加入的資源屬於什麼資源包。
/// 這個參數比較詭異,到底這個參數要依據什麼原則來填寫呢。
/// 其實這個參數的名字OGRE的代碼裏已經定義好了.
/// 如果是文件系統包呢,就查看FileSystemArchiveFactory這個類的定義裏的createInstance,名字爲FileSystem
/// 如果是ZIP壓縮包呢,就查看ZipArchiveFactory這個類的定義裏的createInstance,名字爲Zip
/// 也就是說,這個名字必須以ArchiveFactory的派生類裏定義的爲準,否則肯定會出錯地.
/// 第3個參數就比較簡單了,可以隨便填寫,它只是對資源做一個邏輯上的分類.
ResourceGroupManager::getSingleton().addResourceLocation(
".", "FileSystem", "General");
ResourceGroupManager::getSingleton().addResourceLocation(
"media", "FileSystem", "General");
/**//// 做完以上這步,我們需要把這些資源路徑裏的文件信息都提取出來,以便加速查找.
/// 下面這個函數就是幹這個苦差事的.
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
/**//// 剛剛不是說了嗎,我們把Root裏的第二個參數給留空了,也就是說我們得自己指定一個RenderSystem,
/// 以及給它配置屬性
/// 這裏我們就用在Plugins里加載進OGRE裏的第一個RenderSystem,我這裏是DX
RenderSystem * render_system = *root->getAvailableRenderers()->begin();
/**//// 設置爲窗口模式
render_system->setConfigOption("Full Screen","No");
/**//// 把這個RenderSystem給設爲系統默認的
root->setRenderSystem(render_system);
/**//// 好了,有了RenderSystem,我們就可以初始化我們的Root了.(其實就是創建窗口的過程)
/// 這裏我們把RenderSystem的名字也顯示在窗口的標題欄中.
RenderWindow *render_win = root->initialise(true,String("my simple orge window,rendersystem : ") + render_system->getName());
/**//// 場景的渲染,SceneManager必須創建一個,這個就是我們的遊戲舞臺了
SceneManager * scene_mgr = root->createSceneManager(ST_GENERIC, "my scene");
/**//// 設置燈光的亮度
scene_mgr->setAmbientLight(ColourValue(1,1,1));
/**//// 場景設置好了,但必須還得有個觀察者,這個觀察者在這裏就是Camera
Camera * camera = scene_mgr->createCamera("my camera");
camera->setPosition(Vector3(0,0,500));
camera->lookAt(Vector3(0,0,-300));
camera->setNearClipDistance(5);
/**//// 有了觀察者,但我們怎麼看到場景的內容呢?
/// 我們還得需要一個眼睛,在這裏叫做Viewport
Viewport* vp = render_win->addViewport(camera);
vp->setBackgroundColour(ColourValue(0,0,0));
/**//// 這裏設置camera的圖形比例,必須設置,否則圖象會變形
camera->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
/**//// 我們通過例子裏的資源模型ogrehead來做個演示
Entity *ent = scene_mgr->createEntity("Robot","ogrehead.mesh");
SceneNode *node = scene_mgr->getRootSceneNode()->createChildSceneNode("RobotNode");
node->setPosition(50,30,0);
node->attachObject(ent);
root->startRendering();
delete root;
}
catch (Ogre::Exception & e)
{
::MessageBox( NULL,
e.getFullDescription().c_str(),
"An exception has occured!",
MB_OK | MB_ICONERROR | MB_TASKMODAL);
}
}
本文來自:http://blog.csdn.net/pizi0475/archive/2010/03/18/5389975.aspx
|