Ogre引擎源码——资源管理

1649 篇文章 12 订阅
1623 篇文章 23 订阅

http://blog.csdn.net/hunter8777/article/details/6220866

作为一个图形绘制引擎,需要管理非常多的图形资源,比如纹理、三角网格等。今天就来看下Ogre中资源管理部分。

Ogre中资源管理部分大致包含以下头文件:

OgreResource.h

OgreResourceGroupManager.h

OgreResourceManager.h

这部分代码内容不少,但只要能理清这几个类之间的关系,Resource管理的方式也就可见一斑。

 

先附上一张UML图

Resource UML

中间的三个核心class就是今天的主角。

 

 

(1)Resource

该类定义了所有Ogre中可导入资源的统一接口,保存了资源的信息。该类为抽象类。

  1. /// Creator   
  2. ResourceManager* mCreator;  
  3. /// Unique name of the resource   
  4. String mName;  
  5. /// The name of the resource group   
  6. String mGroup;  
  7. /// Numeric handle for more efficient look up than name   
  8. ResourceHandle mHandle;  
  9. /// The size of the resource in bytes   
  10. size_t mSize;  
  11. /// Optional manual loader; if provided, data is loaded from here instead of a file   
  12. ManualResourceLoader* mLoader;  
  13.   
  14. AtomicScalar<LoadingState> mLoadingState;  

这里列出了Resource类一部分成员变量。

mCreator:每个资源类都是由ResourceManager创建,该变量保留创建者的指针。

mName/mGroup/mHandle/mSize:资源类的名称,所属的组名,句柄以及占用内存大小。

mLoader:一般资源可以有Ogre自动导入,当需要手动进行导入时,需要设置该变量来设定手动导入操作的类,实现不同的导入操作。

mLoadingState:资源当前状态。AtomicScalar<T>是一个封装原子操作的模板类,这个为多线程资源管理提供了可能。

资源状态LoadingState枚举如下

  1. enum LoadingState  
  2. {  
  3.      /// Not loaded   
  4.      LOADSTATE_UNLOADED,  
  5.      /// Loading is in progress   
  6.      LOADSTATE_LOADING,  
  7.      /// Fully loaded   
  8.      LOADSTATE_LOADED,  
  9.      /// Currently unloading   
  10.      LOADSTATE_UNLOADING,  
  11.      /// Fully prepared   
  12.      LOADSTATE_PREPARED,  
  13.      /// Preparing is in progress   
  14.      LOADSTATE_PREPARING  
  15. };  

从上述枚举中可以看出,一个资源有两个非常重要的状态:load和prepare。Resource类中的函数基本也就是围绕着这两个状态改变而进行的。

  1. virtual void preLoadImpl(void) {}  
  2. virtual void postLoadImpl(void) {}  
  3. virtual void preUnloadImpl(void) {}  
  4. virtual void postUnloadImpl(void) {}  
  5. virtual void prepareImpl(void) {}  
  6. virtual void unprepareImpl(void) {}  
  7. virtual void loadImpl(void) = 0;  
  8. virtual void unloadImpl(void) = 0;  

可以看出这些函数的作用就是定义load和prepare前、中。后需要进行的操作。

这里用到了设计模式的Template模板,定义接口,将所有实现都延迟到了子类中。

同时Resource也提供了更细颗粒度的方法来控制load和prepare过程——监听。Resource定义了公共内嵌类Listener,可以通过继承该监听类回调函数,灵活地设置资源状态改变时的操作。

 

引用Resource时,使用的是智能指针。

  1. typedef SharedPtr<Resource> ResourcePtr;  

在ResourceManager中都是以这样的形式出现的。

 

(2)ResourceManager

Resource类是负责具体资源的load和prepare细节,而ResourceManager类是负责创建、删除和调用Resource的,并管理ResourcePool方便同一资源的多次使用。

该类的主要数据结构定义如下:

  1. typedef HashMap< String, ResourcePtr > ResourceMap;  
  2. typedef HashMap< String, ResourceMap > ResourceWithGroupMap;  
  3. typedef map<ResourceHandle, ResourcePtr>::type ResourceHandleMap;  

ResourceMap将资源名称与资源一一对应起来。

ResourceWithGroupMap则是将资源进行一定分组管理。

ResourceHandleMap则是将资源句柄与资源对应。

 

(3)ResourceGroupManager

如果说ResourceManger是对Resource的管理,那ResourceGroupManager就是对ResourceManger的集中管理。刚才提到过ResourceManager中将资源进行了分组管理,ResourceGroupManager就针对这每个分组进行了管理。

分组的信息记录在结构体ResourceGroup中

  1. /// Group name   
  2. String name;  
  3. /// Group status   
  4. Status groupStatus;  
  5. /// List of possible locations to search   
  6. LocationList locationList;  
  7. /// Created resources which are ready to be loaded / unloaded   
  8. // Group by loading order of the type (defined by ResourceManager)   
  9. typedef map<Real, LoadUnloadResourceList*>::type LoadResourceOrderMap;  
  10. LoadResourceOrderMap loadResourceOrderMap;  

上述是ResourceGroup中的部分代码。

该结构体中定义了一个Group的名字、状态、文件所在的位置,以及导入资源的顺序。关于导入顺序,Ogre代码中给出了一个例子,在导入mesh信息前需要导入骨骼和材质,所以后者的优先级就高于前者。

拥有了这样的Group描述信息,ResourceGroupManager就可以进行管理了。

  1. /// Map from resource group names to groups   
  2. typedef map<String, ResourceGroup*>::type ResourceGroupMap;  
  3. ResourceGroupMap mResourceGroupMap;  

默认在ResourceGroupManager构造函数中,创建三个分组General、Internal、Autodetect。

还有另一个重要的结构体ResourceDeclaration。

  1. String resourceName;  
  2. String resourceType;  
  3. ManualResourceLoader* loader;  
  4. NameValuePairList parameters;  

loader是手动导入资源的类指针;parameters用于StringInterface类设置类成员变量。

该结构定义了一个资源的信息,但注意,Ogre中定义了一个资源并没有真正地将它导入进来,也就是并没有生成资源句柄,只是录入了一些资源信息而已。

这些数据结构定义就是用来保存ResourceDeclaration信息的,ResourceDeclaration同样也保存在ResourceGroup中。

  1. /// List of resource declarations   
  2. typedef list<ResourceDeclaration>::type ResourceDeclarationList;  
  3. typedef map<String, ResourceManager*>::type ResourceManagerMap;  

 

这样我们就能理清Ogre处理一个资源的简单流程了。

1、Ogre启动时对外部资源并不知晓,通过添加资源名称、组名、文件路径等信息,录入资源信息(通常Ogre通过外面脚本定义资源路径);

2、将一个资源归入一个资源组,并通过定义的信息,在内存中实例化相应的资源(具体的创建过程是由ResourceManager调用Resource完成的);

 

附上一张做得不错的资源状态转换图

状态转换图

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值