笑看风云

记录生活中的启迪与感动
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

[转]BSP技术详解(补充)--------------pvs算法

Posted on 2010-02-01 10:25  清晨的风  阅读(675)  评论(0编辑  收藏  举报

终于将HL2的vbsp,vvis看完了,随便也翻了翻q3map代码,发现两者的代码太相似了,
可以看出在BSP分割,portal的查找方面在Q2中都应该已经定型了,因此两者使用的
算法都是一样的。下面我主要谈一下计算pvs的算法,因为在我翻译的那篇文章
《bsp技术详解》中计算pvs是通过在每个portal上确定一些采样点然后进行ray cast
来计算pvs的,这种方法的速度没有保证,而且处理起来也非常麻烦。而ID通过对
每一个portal的polygen进行clip的方法来获取pvs,确实速度上要比上一个方法好上
很多。下面我来对算法进行详细的介绍,如果你对bsp不是很熟的话需要明确一下几个
概念,一个是cluster,对于室内场景来说它完全是由cluster组成的,简单的你可以
将它认为是场景中的一个房间,另一个是portal,场景中的cluster是由portal连接
为一个整体,你可以把它看作是房间的门或窗户。在进行pvs计算的时候已经将整个
场景划分为bsp tree,查找完portal并将cluster和leaf node连接起来了。
1、首先对所有的portal先进行一下预处理,让一个portal只和一个cluster发生联系,
这样作的目的是为了获得一个单向的portal,也就是说portal只在一边可见,这样做
是为了方便进行处理。我们知道一个portal通常连接了两个cluster,一般情况下使
用的是portal所在plane
正面的portal,但为了达到上述目的,我们需要将portal分为正反两个,由于在bsp
中每一个plane都保存正反两个,因此位于反面的portal只需要对ploygen颠倒一下
顶点顺序即可。这里规定一个portal只和位于其plane的法线方向上的cluster发生
联系,预处理后保存的portal数量是原来的2倍。
2、接着我们需要对portal进行一下分类处理。通过简单的常识我们知道,由于现在
每一个portal都是单向可见,因此只有位于portal可见方向(称为front方向)的
portal才可能是可见的,我们需要对每一个portal都获得一个front portal列表并
保存起来。
3、下面我们需要进一步的对每一个portal的front portal列表中不可见的portal进行
剔除。我们知道场景完全是由一个个portal连接起来的cluste组成的,对于一个portal
来说位于同一个cluster的portal一定可见,而其他portal要想可见最基本的要求是
它可以通过其他portal连接到这个cluster上,因此通过portal的连接关系我们可以
从front portal列表中剔除那些和当前portal没有连接关系的portal,并保存到flood
portal列表中。
4、好了经过上面的处理我们已经剔除了大部分不可见的portal,可见的portal一定
包含在flood portal列表中,因此需要使用更精确的方法进行检查。为了方便描述,
我假定当前计算pvs的portal为A,任选和A所在的cluster ca相连的一个portal称为B,
注意B一定是可见,因此B所在的cluster cb一定可见,但是和cb相连的其它portal
并不一定可见,为了检查是否可见,我们假定选取其中的一个portal称为C。好了
现在的问题简化为已知A和B求C是否可见,算法如下:
在A上选取一条边和B上的一个顶点构成一个clip plane,为了保证这是一个合法的
clip plane我们需要做一下检查,为了简单化我们首先需要保证clip plane的法线
方向必须指向portal A的外部,也就是说A上所有的顶点都位于clip plane的背面。
其次我们要保证portal B上所有的顶点都位于clip plane的正面,这样做可以保证
当你选择A上最左边的一条边时必须要和B上最右边的一个顶点构成clip plane,当
你选择A上最右边的一条边时必须要和B上最左边的一个顶点构成clip plane,将所
有的clip plane合并起来实际上就获得一个A到B的最大可见frustum,只有位于frustum
内部的portal才是可见的。当建立起这个frustum后我们就可以使用它对C的polygen
进行clip操作了,当C clip后如果没有polygen在frustum内部那么它是不可见的,
否则portal C可见并将可见的polygen保存下来。当C可见后我们需要接着对和C相连
的portal进行检查,方法还是一样不过上面的portal B变成了C而且必须要注意,
建立frustum使用C的polygen应该是clip后的polygen数据。通过上面的方法对A的
flood portal列表进行递归运算最终将获得一个真正的可见portal集合保存到
vis portal列表中。还需要指出一点的是建立clip plane的过程实际上需要两次,
第一次是从A到B,第二次是从B到A,这样做的原因是并不是所有的极值点都位于B上
的,也可能位于A上因此需要进行两次。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/olncy/archive/2009/03/31/4038305.aspx