logo资料库

华南理工大学软件学院游戏引擎实验源码分析.docx

第1页 / 共8页
第2页 / 共8页
第3页 / 共8页
第4页 / 共8页
第5页 / 共8页
第6页 / 共8页
第7页 / 共8页
第8页 / 共8页
资料共8页,全文预览结束
实 验 二 报 告 (2018-2019 学年第二学期) 3D 游戏引擎架构设计基础 (Foundations of 3D Game Engine Architecture Design) 学生姓名 成绩: 实验题目: 学号: 年级 16 级,班级:5 班 任课教师签名: 日期: 目录: 1. 实验内容描述: 引擎名称和版本,将分析的引擎模块名称 2. 将分析的引擎模块的主要功能描述 3. 将分析的引擎模块的主要类和类关系描述 4. 类的数据成员和成员函数描述 5. 总结 实验报告: 版本:1.11.5 1. 引擎名称:OGRE 模块名称:资源模块 2. 游戏资源管理主要做什么? ·资源组织 根据各种资源的特性和使用的方式等,设计资源数据的内存组织方式 ·资源管理 统一的资源处理方法,如:内存分配、资源状态管理、加载和卸载操作、资源调度算法、以 及多线程管理等 游戏资源管理目的:通过有效地组织和管理各类资源,能在合适的时候、快速地提供给游戏 程序。 游戏资源管理的种类  文件管理:游戏的资源是以文件的形式存储的 ·包括文件的加载和卸载,文件解析,格式转换,打包和传输资源文件等。  内存管理:使用资源时需要加载到内存 ·内存分配 ·访问保证 ·内存释放  状态管理:资源当前的状态,如已定义、已加载、已移除等
 资源调度算法:在有限的内存中,为使用资源的程序提供最好的方案 ·优先队列 ·LRU  多线程处理:资源管理的并行处理 3. 类和类关系描述 3.1 主要类的关系 简单来说,他们之间的关系 Resource、ResourceManager、ResourceGroupManager 这三个类是 OGRE 引擎进行资源 管理的三个核心类,Ogre 把资源分为“Font”、“GpuProgram”、“Material”、“Mesh”、 “Skeleton”和“Texture”等类型,它们分别用 Font、GpuProgram、Material、Mesh、Skeleton、 Texture 等同名的类对象来描述,这些类都直接从 Resource 基类派生。Ogre 的 Resource 对象 都由 ResourceManager 来管理。不同类型资源的管理,分别由不同的资源管理器来实现,比 如以上各种类型资源都对应着各自的资源管理器,FontManager、GpuProgramManager、 MaterialManager 、 MeshManager 、 SkeletonManager 、 TextureManager 等 , 它 们 都 以 ResourceManager 作为自已的基类。各种类型资源类对象的创建、Load/Unload、销毁等操作, 都由相应的 ResourceManager 来完成。但 Ogre 的对资源的管理还不仅限于此。为了更方便 资源的使用,提高资源的使用的效率。Ogre 中有一个被称为 ResourceGroupManager 的类,
其 中 内 嵌 了 一 个 ResourceGroup 的 结 构 定 义 , 很 明 显 定 义 ResourceGroup 只 是 为 了 ResourceGroupManager 内部使用。在需要进行 3D 场景展示的一般应用中,经常会遇到需要 进行场景切换的时候,比如游戏中的关卡切换时,虚拟现实中角色由一个地点转换到另一个 地点时等等。而在渲染每个场景时所需的资源往往涉及了所有的资源类型,一旦场景发生切 换,当前所使用的大量资源都需要被逐一卸载,而新的场景所需的各类资源要逐一被加载。 在游戏编程时,可以在自已编写的关卡管理器中处理类似工作,这明显会产生额外的工作量, 更麻烦的是这部分代码逻辑可能需要在每个应用中被重复编写,而如果借助 Ogre 提供的 ResourceGroup 就可以直接方便地实现类似功能了。 Ogre 处理一个资源的简单流程:1、Ogre 启动时对外部资源并不了解,通过添加资源名称、 组名、文件路径等信息,录入资源信息(通常 Ogre 通过外面脚本定义资源路径)。2、将一 个资源归入一个资源组,并通过定义的信息,在内存中实例化相应的资源(具体的创建过程 是由 ResourceManager 调用 Resource 完成的)。 4. Undefined:这是程序开始时,所有资源的缺省状态。除非它们被声明,ogre 对程序用到的资 源一无所知,手工调用代码 ResourceGroupManager::declareResource()或在脚本中被解析之 后,资源的状态变为 Declared Declared:声明就是告诉 ogre 想要加载某些资源。ResourceGroupManager::declareResource() 总是有效的,包括在渲染系统初始之前,这与 ResourceManager::create()不同,因为后者依 赖于渲染系统。 Unloaded:通过调用 ResourceGroupManager::initialiseAllResourceGroup(),ResourceGroupManager::initialiseResource Group(),或 Root::initialise()(它会初始化在此调用之前所有声明的资源),资源状态进入到 Unloaded,资源会占用一点内存来保存它的定义的实例,但是资源本身还没有加载到内存。 从另一角度看(从 Loaded 到 Unloaded),引起状态变化的调用有: ResourceManager::unload(),ResourceManager::unloadAll(),
ResourceManager::unloadAllUnreferencedResources(),ResourceGroupManager::unloadResource Group(), or Resource::unload().所有这些调用仍会保存资源实例,但真正的资源数据会从内存 中卸载。 Loaded: 这 种 状 态 下 , 所 有 数 据 都 变 得 有 效 。 与 此 状 态 有 关 的 调 用 有 Resource::load(), ResourceManager::reload(), Resource::reload(), ResourceManager::reloadAll(), and ResourceGroupManager:: loadResourceGroup(). ResourceManager::reloadAllUnreferencedResources(), ResourceManager::load(),  Resource 该类定义了所有 Ogre 中可导入资源的统一接口,保存了资源的信息。该类为抽象类 类的定义如下 /// Creator ResourceManager* mCreator; /// Unique name of the resource String mName; /// The name of the resource group String mGroup; /// Numeric handle for more efficient look up than name ResourceHandle mHandle; /// The size of the resource in bytes size_t mSize; /// Optional manual loader; if provided, data is loaded from here instead of a file ManualResourceLoader* mLoader; mCreator:每个资源类都是由 ResourceManager 创建,该变量保留创建者的指针。 mName/mGroup/mHandle/mSize:资源类的名称,所属的组名,句柄以及占用内存大小。 mLoader:一般资源可以有 Ogre 自动导入,当需要手动进行导入时,需要设置该变量来设 定手动导入操作的类,实现不同的导入操作。 mLoadingState:资源当前状态。AtomicScalar是一个封装原子操作的模板类,这个为多线 程资源管理提供了可能。 资源状态 LoadingState 枚举如下 enum LoadingState { /// Not loaded LOADSTATE_UNLOADED, /// Loading is in progress LOADSTATE_LOADING, /// Fully loaded LOADSTATE_LOADED, /// Currently unloading LOADSTATE_UNLOADING, /// Fully prepared LOADSTATE_PREPARED,
/// Preparing is in progress LOADSTATE_PREPARING }; 从上述枚举中可以看出,一个资源有两个非常重要的状态:load 和 prepare。Resource 类 中的函数基本也就是围绕着这两个状态改变而进行的。 virtual void preLoadImpl(void) {} virtual void postLoadImpl(void) {} virtual void preUnloadImpl(void) {} virtual void postUnloadImpl(void) {} virtual void prepareImpl(void) {} virtual void unprepareImpl(void) {} virtual void loadImpl(void) = 0; virtual void unloadImpl(void) = 0; 可以看出这些函数的作用就是定义 load 和 prepare 前、中。后需要进行的操作。 这里用到了设计 模式的 Template 模板,定义接口,将所有实现都延迟到了子类中。 同时 Resource 也提供了更细颗 粒度的方法来控制 load 和 prepare 过程——监听。Resource 定义了公共内嵌类 Listener,可以通过 继承该监听类回调函数,灵活地设置资源状态改变时的操作。 引用 Resource 时,使用的是智能指针。 typedef SharedPtr ResourcePtr; 在 ResourceManager 中都是以这样的形式出现的。  ResourceManager Resource 类是负责具体资源的 load 和 prepare 细节,而 ResourceManager 类是负责创建、删除和调 用 Resource 的,并管理 ResourcePool 方便同一资源的多次使用。 该类的主要数据结构定义如下: typedef HashMap< String, ResourcePtr > ResourceMap; typedef HashMap< String, ResourceMap > ResourceWithGroupMap; typedef map::type ResourceHandleMap; ResourceMap 将资源名称与资源一一对应起来。 ResourceWithGroupMap 则是将资源进行一定分组管理。 ResourceHandleMap 则是将资源句柄与资源对应。  ResourceGroupManager 如果说 ResourceManger 是对 Resource 的管理,那 ResourceGroupManager 就是对 ResourceManger 的 集中管理。刚才提到过 ResourceManager 中将资源进行了分组管理,ResourceGroupManager 就针对 这每个分组进行了管理。 分组的信息记录在结构体 ResourceGroup 中 /// Group name String name; /// Group status Status groupStatus;
/// List of possible locations to search LocationList locationList; /// Created resources which are ready to be loaded / unloaded // Group by loading order of the type (defined by ResourceManager) typedef map::type LoadResourceOrderMap; LoadResourceOrderMap loadResourceOrderMap; 上述是 ResourceGroup 中的部分代码。 该结构体中定义了一个 Group 的名字、状态、文件所在的位置,以及导入资源的顺序。关于导入顺序, Ogre 代码中给出了一个例子,在导入 mesh 信息前需要导入骨骼和材质,所以后者的优先级就高于前 者。 拥有了这样的 Group 描述信息,ResourceGroupManager 就可以进行管理了。 /// Map from resource group names to groups typedef map::type ResourceGroupMap; ResourceGroupMap mResourceGroupMap; 默认在 ResourceGroupManager 构造函数中,创建三个分组 General、Internal、Autodetect。 还有另一个重要的结构体 ResourceDeclaration。 String resourceName; String resourceType; ManualResourceLoader* loader; NameValuePairList parameters; loader 是手动导入资源的类指针;parameters 用于 StringInterface 类设置类成员变量。 该结构定义了一个资源的信息,但注意,Ogre 中定义了一个资源并没有真正地将它导入进来,也就 是并没有生成资源句柄,只是录入了一些资源信息而已。 这些数据结构定义就是用来保存 ResourceDeclaration 信息的,ResourceDeclaration 同样也保存在 ResourceGroup 中。 /// List of resource declarations typedef list::type ResourceDeclarationList; typedef map::type ResourceManagerMap; Ogre 处理一个资源的简单流程了。 1、Ogre 启动时对外部资源并不知晓,通过添加资源名称、组名、文件路径等信息,录入资源信 息(通常 Ogre 通过外面脚本定义资源路径); 2、将一个资源归入一个资源组,并通过定义的信息,在内存中实例化相应的资源(具体的创建 过程是由 ResourceManager 调用 Resource 完成的); 5.下面是游戏资源的加载和创建过程:
实验总结: 本次实验我研究了 OGRE 的资源管理模块。了解了其中的流程,感觉收获很大。
分享到:
收藏