[转]OGRE资源的四种状态

未定义
    游戏程序启动时所有资源的默认状态,资源未被索引,所以OGRE不知道它们的存在。
已声明
    资源已被索引,OGRE已经知道这些资源的存在,但它们还没被初始化。
    (平时我们读取了资源配置文件之后,资源就进入了这种状态。)
未载入
    资源已被初始化——被初始化的资源都生成了一个分别对它们的引用(这些引用会占用小部分内存),但资源还没被载入到内存。
    p.s.:如果某个资源有一个脚本,则脚本也已被解析完毕。
    (平时我们调用“ResourceGroupManager::getSingleton().initialiseResourceGroup("General");”函数后,之前被索引的资源就进入未载入状态。)
已载入
    资源被激活,资源数据存在于内存中,可以被游戏程序直接调用了。(如果游戏程序调用未载入的资源,并且资源管理器的内存配额没有超出,则OGRE会自动帮你载入这些资源。)
    (平时我们调用“ResourceGroupManager::getSingleton().loadResourceGroup("General");”函数后,之前已被初始化的资源就进入已载入状态,它们占有内存空间。)

本文出自 51CTO.COM技术博客

 

 

 

资源组
命名组可以作为一个整体加载与卸载。在加载,卸载,初始化时把把组中的所有资源作为一个执行单位来
看待,而不是逐个进行处理。资源组管理纯粹是了为了管理上的方便,是否使用组的方式与性能无关。假
如向资源组管理器中加入了资源位置而没有指定组名,那么这些资源位置被放入"General"组中。


资源组与世界几何
缺省情况下,ogre把加载的世界几何放入"General"组。也可以覆盖(override)这种方式,使得对世界几何的管理像其他资源的管理方式一样。统一的场景管理器可以提供关于装载世界总步骤的线索,这样就可以在关卡加载时,提供精确的以进度条显示的反馈信息。

资源位置(location)
资源位置是ogre去查找资源进行索引的地方。索引指的是在某个位置的所有资源通过它们的名字被映射,这样可以方便进行更快的查找资源。可以在程序的任何时候添加或删除资源位置,不必事先对所以可能用到的进行定义。资源位置在ogre中实际上是个archive,它的意思就是“文件的集合”。磁盘上的文件系统是archive的一种类型。另外一种是zip archive。可以自定义archive格式。这通过改写archive类实现来完成,必须支持对命名的leaf文件进行枚举操作,必须支持通配符,支持结点递归,给ogre提供一个流访问archive中文件的数据。ogre中的archive是只读的。ogre资源管理器利用archive枚举特性来索引archive的内容,当ogre对archive进行索引时,不会实际加载任何资源。

资源生命周期
资源有四种状态,各状态之间的转换关系如下图:



Undefined:这是程序开始时,所有资源的缺省状态。除非它们被声明,ogre对程序用到的资源一无所知,手工调用代码 ResourceGroupManager::declareResource()或在脚本中被解析之后,资源的状态变为Declared
Declared:声明就是告诉ogre想要加载某些资源。ResourceGroupManager::declareResource()总是有效的,包括在渲染系统初始之前,这与ResourceManager::create()不同,因为后者依赖于渲染系统。
Unloaded:通过调用ResourceGroupManager::initialiseAllResourceGroup(), ResourceGroupManager::initialiseResourceGroup(),或Root::initialise()(它会初始化在此调用之前所有声明的资源),资源状态进入到Unloaded,资源会占用一点内存来保存它的定义的实例,但是资源本身还没有加载到内存。从另一角度看(从Loaded到Unloaded),引起状态变化的调用有:ResourceManager::unload(),ResourceManager::unloadAll(), ResourceManager::unloadAllUnreferencedResources(),ResourceGroupManager::unloadResourceGroup(), or Resource::unload().所有这些调用仍会保存资源实例,但真正的资源数据会从内存中卸载。
Loaded: 这种状态下,所有数据都变得有效。与此状态有关的调用有Resource::load(), Resource::reload(),ResourceManager::load(), ResourceManager::reload(), ResourceManager::reloadAll(),ResourceManager::reloadAllUnreferencedResources(), and ResourceGroupManager::loadResourceGroup().

逻辑资源管理
资源以命名组的形式组织,每组可以包括任何类型的资源,每种资源都有自己的资源管理器,后者负责加载与卸载特定类型的资源。ogre对它的资源没有实现特定的内存管理方案,如果你需要对某种资源实“最近最少使用算法”方案来进行管理,那么需要自己的代码来实现。值的一提的是,现在的大多数显卡驱动,对于大多数重要的资源已经实现了这种LRU算法管理。

资源加载
假如没有预加载,当资源被访问时会进行加载。实际的加载,卸载是资源自己的责任。

手动加载资源
资源管理层不负责实际的加载与卸载。通常,不必担心资源是否存在于易失性媒介。然而,手工方式时需要考虑。手工资源加载器必须在任何时候准备好重新加载资源。假如某个资源是通过程序生成的,那么手工资源加载器必须内存中缓冲这些资源,或者是当资源管理加载时重新创建它。ogre认为手工加载与自动加载没有区别。

后台资源管理
缺省,ogre不是线程安全的。假如在OgreConfig.h中 #define OGRE_THREAD_SUPPORT 1 ,那么资源管理
代码的线程同步功能变得有效,我们就可以在包含Root实例的线程之外,开启新的线程对资源管理类与方法进行操作,从而实现灵活的资源加载方案。

非后台资源管理
Ogre中大量使用了Observer模式,资源管理系统也不例外。ResourceGroupListene 回调接口包含了几个方法
允许对资源加载过程进行细粒度的监听。

资源卸载
资源被加载后总存在于内存中,直到被应用程序强行卸载(通过资源组管理器或是被资源直接释放)。资源管理组管理会把组中所有的资源都卸载掉。在资源被引用时不能强行卸载。

Resource Locations

// 配置文件方式
ConfigFile cf;
cf.load("resources.cfg");
// Go through all sections & settings in the file
ConfigFile::SectionIterator seci = cf.getSectionIterator();
String secName, typeName, archName;
while (seci.hasMoreElements())
{
secName = seci.peekNextKey();
ConfigFile::SettingsMultiMap *settings = seci.getNext();
ConfigFile::SettingsMultiMap::iterator i;
for (i = settings->begin(); i != settings->end(); ++i)
{
typeName = i->first;
archName = i->second;
ResourceGroupManager::getSingleton().addResourceLocation(
archName, typeName, secName);
}
}


//硬编码方式
ResourceGroupManager *rgm = ResourceGroupManager::getSingletonPtr();
rgm->addResourceLocation("../../media/packs/OgreCore.zip", "Zip", "Bootstrap");
rgm->addResourceLocation("../../media", "FileSystem", "General");
rgm->addResourceLocation("../../media/fonts", "FileSystem", "General");

 

初始化
在初始化之前,必须创建至少一个渲染窗口。因为在分析脚本时可能会创建GPU资源,而后者需要渲染上下文。


// initialize all of the previously defined resource groups
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
// or, alternately, initialize the defined resource groups one at a time
ResourceGroupManager::getSingleton().initialiseResourceGroup("General");
ResourceGroupManager::getSingleton().initialiseResourceGroup("Bootstrap");


卸载
可以在任何时候卸载资源(以组或单个的方式),正在使用的资源不会被卸载。

以组的方式卸载
ResourceGroupManager::getSingleton().unloadResourceGroup("Bootstrap", true);
ResourceGroupManager::getSingleton().
unloadUnreferencedResourcesInGroup("Bootstrap", true);
true表示只卸载资源数据,不删除资源实例,它可以被reloaded。有些资源在创建时被标为
"nonreloadable",这种类型的资源不能使用上述方法卸载。

清理或销毁资源组
清理仅是卸载资源与分离资源索引,销毁不仅做清理的工作,还包括从资源组中把自己移除。
ResourceGroupManager::geSingleton().clearResourceGroup("Bootstrap");
ResourceGroupManager::geSingleton().destroyResourceGroup("Bootstrap");

以个体方式卸载
// assume that pEntity is a valid pointer to an instance of Entity
MeshPtr meshPtr = pEntity->getMesh();
meshPtr->unload();

加载/重载资源组
ResourceGroupManager::getSingleton().loadResourceGroup("Bootstrap", false, true)
二个布尔变量不同资源类型资源加载开关,一针对"Normal"资源,二针对"World geometry"

资源组加载通知
class LoadingProgressListener : public ResourceGroupListener
{
   public: 
// fired when a group begins parsing scripts
                void resourceGroupScriptingStarted(const String& groupName,
                                                                        size_t scriptCount) {}
// fired when a script is about to be parsed
               void scriptParseStarted(const String& scriptName) {}
// fired when the script has been parsed
               void scriptParseEnded() {}
// fired when all scripts in the group have been parsed
              void resourceGroupScriptingEnded(const String& groupName) {}
//还有一些接口
}


//实现之后,进行注册
LoadingProgressListener listener(m_progressMeter);
ResourceGroupManager::getSingleton().addResourceGroupListener(&listener);

posted @ 2012-11-19 17:35  Pulaski  阅读(846)  评论(0编辑  收藏  举报