【Java精品源码栏目提醒】:网学会员在Java精品源码频道为大家收集整理了“【精品】3D引擎场景管理 - 其它资料“提供大家参考,希望对大家有所帮助!
3D 引擎场景管理 我认为对于一个 3D 引擎来说,最核心的部分应该算是场景组织(scene graph)了,如果这部分你都没有设计好, 那么就别指望开发一个成熟的 3D 引擎了。
为了开发 3d 引擎,所以我首先就研究这方面的内容,对一个 3D 的场景来说,又很多的物体,最简单的组织方法就是把他们用一个 List 连接起来,然后在绘制没一帧的时候依次送入渲染器(render)进行处理。
这显然不是一个很有效的方法,当处理一个普通的游戏场景都会显得非常慢的。
实际上虽然一个场景中的物品很多,但是通常可见的指是以小部分,如何能够用很小的计算代价排除那些不可见的物品呢,这种方法叫做剔除隐藏面,减少绘制元素(Hidden Surface Complexity Reduction)。
为了实现这样的方法,牵涉到空间排序(Spatial Sorting),最基本的方法要算二叉空间分割树(BSP)了,DOOM 是第一个使用了二叉树的商业游戏。
二叉树的构造简单地说就是对于要处理的一组对象,选择一个平面,将该组对象分成两组(如果由某个对象与该平面相交则用这个平面将这个对象分成两个对象)作为该结点的两个儿子,然后分别对两组对象用相同的方法,直到满足一个特定的条件(通常是到结点上只有一个对象)为止。
二叉树确实是一种很有效的场景组织结构,因为,当给出视锥(view frustum)以后,在穿过(traverse)这棵树的时候,如果发现视锥(frustum)与结点所代表的平面不相交,那么这个结点上有一棵子树必然不可见那么这个子树就不用送入渲染器了,当遇到 Leaf 的时候,就可以获得所需的多边形数据,可以送入渲染器处理。
虽然二叉树已经是非常有效的方法,但是仅仅依靠二叉树还是不能满足游戏的要求,因为现在的游戏的场景是在是很大很复杂,又很多的物品,按照二叉树的方法凡是与 view frustum 相交的 Leaf 必然要送入渲染器,因为 view frustum是很大的,所以会有很多的 Leaf 与他相交,这就意味着渲染器还是要处理很多的数据,如果你确实能够看到这么多的物体,那也没有办法,但是通常,比如很多室内的场景,虽然在你的 frustum 里面会由很多物体,但是你真正能够看到的还是很少的一部分,比如一个封闭的房间。
因此被称为 Portal 的技术被引入到游戏中来,之所以能够使用 Portal 技术,那是因为很多室内场景自身的限制条件所致。
我们引入 region 的概念,一个 region 就是一个相对封闭的空间,比如一个房间,region 与 region 之间都是通过 Portal(比如门或窗)相连接,因此,如果你处于一个 region 当中,你就只能看到这个 region 中的物体,如果你能够看到其他 region 中的物体,那么你一定是通过 Portal 看到的,所以处理的过程如下(考虑 Portal 是单向的情况,如果两个 region 可以通过一个门相互看到,我就是用两个单向的 Portal)。
void CRegion::DrawLPRender lpRender_ if m_bVisited return // 防止两个相邻的 region 的 Portal 形成死循环 m_bVisited TRUE for int i0ilt m_NumOfPortalsi if m_aPortalsi.m_bOpen // 如果 Portal 在 view frustum 中 if lpRender-gtCullm_aPortalsi m_aPortalsi.m_pRegion-gtDrawlpRender_ m_apObjects-gtDrawlpRender_ m_bVisited FALSE 通常我们使用二叉树的方法来组织 region,理想的情况下每个二叉树树的 Leaf 就是一个 region,通过二叉树的遍历可以很容易的找到照相机(camera)所在的 region。
不过我觉得实际做场景的时候不会这么理想,因该是一个 region可能被划分成了几个 leaf,不过只要保证每个 leaf 一定属于某个 region,我们就可以对每个 leaf 增加一个 region 的引索(index),同样可以很方便的找到所在的 region。
Portal 引擎的一个不太好的地方就是,你必须手动设定许多 Portal,设计场景的会有一些限制,否则得不到很好的效果。
在了解了这些技术以后我又去看了“Genesis3D”的源代码,只看了场景组织的部分,我先把我的理解说一下。
Trace.h