OGRE资源相关分析 + OGRE 启动详解 + 实体的加载与显示
2011-04-22 13:19
573 查看
[align=center]OGRE资源相关分析[/align]
Resource
Resource的类继承体系如下:
![](http://student.csdn.net/attachment/201104/22/719157_1303449487KaHK.jpg)
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的类继承体系如下:
![](http://student.csdn.net/attachment/201104/22/719157_1303449486Bbz7.jpg)
和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 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分析]
[align=center]OGRE 启动详解 + 实体的加载与显示[/align]
Resource
Resource的类继承体系如下:
![](http://student.csdn.net/attachment/201104/22/719157_1303449487KaHK.jpg)
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的类继承体系如下:
![](http://student.csdn.net/attachment/201104/22/719157_1303449486Bbz7.jpg)
和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()); |
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 程序就写好了,很简单吧。当初写的时候碰到不少问题,主要是文件找不到,资源找不到…… |
#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 |
相关文章推荐
- OGRE 学习笔记(启动详解 + 实体的加载与显示)
- OGRE 学习笔记(启动详解 + 实体的加载与显示)
- OGRE 启动详解 + 实体的加载与显示
- Android 游戏引擎libgdx 资源加载进度百分比显示案例分析
- Android App启动时Apk资源加载机制源码分析
- Android App启动时Apk资源加载机制源码分析
- (转)OGRE资源相关分析
- iOS:App启动过程详解(相关资源xib等的访问)
- Linux内核启动代码分析二之开发板相关驱动程序加载分析
- Linux内核启动代码分析二之开发板相关驱动程序加载分析
- 【转】OGRE资源相关分析
- Entity Framework加载相关实体——延迟加载Lazy Loading、贪婪加载Eager Loading、显示加载Explicit Loading
- 搭建RAC用sqlplus启动db资源显示offline问题分析处理
- U盘病毒及其相关资源的分析(patch shell32.dll)
- 解决启动程序时先显示带title的白背景,后加载Activity的问题
- UCOSII启动流程详解(结合源码分析)
- Android源码分析-资源加载机制
- Tomcat启动时项目重复加载,导致资源初始化两次的问题
- Android开源框架分析1—下拉刷新&加载更多实现方式详解
- 页面DOM-资源加载的相关标识