场景图一直被认为是适合游戏的通用场景管理算法,仿佛没实现过场景图就不算写过引擎。但是经过思
考和分析,我觉得场景图并不适合作为一种通用的场景组织方式,在下面我会说明理由,并提出一种替代的
适合目前mmorpg网游的场景管理方式。如果大家有什么不同看法可以和我讨论。
场景图是一种层级组织场景的数据结构,要生成场景图就要选择一种层级关系,或曰父子关系,或曰继
承关系。比如几何变换矩阵的级联关系,或者空间范围的包围关系,或者渲染属性的继承关系。然而你选择
了一种关系就不得不放弃另一种关系,或者你不得不在不同层级或者不同枝杈间选择不同的级联关系而使系
统变得复杂晦涩。另一方面并不是所有的系统都是层级关系,比如地形更适合用四叉树或者是数组结构来组
织(我觉得对于目前网游的可视范围来说数组就很好了,根本不需要四叉树),室内场景更适合用通过
Portal连接的区域这种类似图的结构来组织,如果生硬的将这些结构附和到级联关系的场景图,将难以设计
,带来混乱。很多不好的场景图的实现往往带来扁平的场景组织结构,场景图就像一个链表,失去了层级组
织的优势。
下面我提出一种适合目前mmorpg网游的场景管理方式:
首先定义一个场景管理器接口ISceneMgr,包括如下接口函数(仅列举讲解思路所必须的函数):
class ISceneMgr
{
public:
绘制函数
一组碰撞检测函数
}
从ISceneMgr接口派生两个场景管理器类,分别是地形管理器ITerrainMgr和室内场景管理器
IBuildingMgr,地形管理器通过数组结构组织管理地形Patch,室内场景管理器通过Portal连接的区域组成的
类似图的结构管理室内场景。
假设一块地形上有一座城堡,让我们来看看上面的结构如何完成游戏功能。地形管理器会通过室内场景
(城堡)的最大包围盒、城堡所覆盖的地形Patch区域、和连接室内外区域的Portal与室内场景发生联系。首
先来看绘制过程,假如摄像机在地形区域,地形管理器会通过数组结构、地平线算法、PVS可能可见级来做绘
制裁减和剔除的优化,如果城堡的包围盒在视锥范围内则交给室内场景管理器进行绘制。室内场景管理器会
通过Portal做遮挡剔除来优化绘制过程。如果摄像机在室内,则首先由室内场景管理器进行绘制,如果摄像
机通过连接室内外的Portal看到了室外场景再把绘制交给地形管理器。
再来看看碰撞检测,以射线的碰撞检测为例,如果射线的起点在室外地形,则先由地形管理器做检测,
同样可以利用地形的一切特点进行碰撞检测的优化。如果射线与城堡的最大包围盒相交,则把检测交给室内
场景管理器,同样的室内场景管理器可以利用Portal、bsp树等一切可以利用的室内场景特性做检测的优化。
假如射线的起点在室内,则先由室内场景管理器做检测,如果射线穿过了一个连接室内外的Portal,再把射
线交给地形管理器去检测。
看上去不错,也许有些人会问那模型系统、特效系统怎么办,都作为场景管理器岂不是会有越来越多的
管理器,碰撞检测和绘制要遍历越来越多的系统?其实不然,模型和特效我们不把它们看成是场景管理器,
而是作为更低一级的底层对象,它们必须依赖一个场景管理器对象而存在,也就是说它们必须属于一个地形
系统或一个室内区域,它们的绘制和碰撞检测由它们所属的场景管理器对象驱动,不同的管理器会通过各自
特殊的数据结构来优化对模型和特效的管理,比如地形系统纪录模型所在的地形Patch,室内场景管理器纪录
模型所在的区域(房间)。
一切就这么简单、清晰,不需要去附和到一个统一的结构,各个系统有各自的特点,有自己的优化组织方
式,放弃场景图,你将远离烦恼。
找到一篇与我观点相近的文章,链接如下,有兴趣的朋友可以参考。
http://home.comcast.net/~tom_forsyth/blog.wiki.html 中的“Scene Graphs - just say no”主题