去除多余的Portal

来源:互联网 发布:马云的阿里帝国疆域图 编辑:程序博客网 时间:2024/05/01 02:01

                                                            去除多余的Portal

 本来很少的一点东西说了那么多,感觉自己挺罗嗦的。如果您发现这篇文章中有错误,
或着您有更好的方法,请发邮件告诉我。
大部分介绍使用程序自动生成Portal 的文章里都有一个问题——它们所介绍的算法都
会产生一些多余的Portal。而关于如何在生成Portal 之后去除那些多余的Portal 却没有提。
本文讨论了如何在自动生成Portal 的时候使用一些检测方法来去除多余的Portal。
在阅读本文前你应该已经了解了BSP 和Portal 的相关知识,并且知道如何去创建一棵
BSP树,并生成Portal。如果您不了解的话我向您推荐以下这两篇文章:
《Binary Space Partioning Trees and Polygon Removal in Real Time 3D Rendering》。这篇文章
可以说是介绍了有关BSP 的全部东西,包括BSP,Portal,PVS,基于BSP的Radiosity,基
于BSP的Collision等。国内的dreams_wu将这篇文章翻译了过来,叫做《BSP技术详解》
可以在网上很容易的找到。
‚《Automatic Portal Generation》。作者是Huling和LiZhenxiao,发布在www.gamedev.net。
介绍了如何使用程序自动生成Portal。国内的noslopforever(天堂里的死神)将这篇文章翻
译了过来,叫做《自动Portal生成》可以在他CSDN上的blog (http://blog.csdn.net/noslopforever/)
和www.gameres.com上找到。
为什么会产生多余的Portal?
关于Portal 的生成在中有介绍,但那个方法并不是很好。‚里边的算法针对进行了
一些改进,但还是会产生一些多余的Portal。下面我们以‚里边的算法为例先了解一下生成
Portal的整个过程。
我们已经知道生成一个Portal 需要以下3 步:(在程序中这3 步往往都是结合在了一起)
1. 根据BSP树的性质,所有的Portal 都是在分割面上的,所以第1 步就是在分割面上生成
一个足够大的多边形(一般都是矩形)作为初始的Portal。
2. 确定这个Portal 连接了哪两个叶子。
3. 使用Portal 所连接的两个叶子里的多边形和从树根到这两个叶子所经过的那些分割面来
切割这个Portal,切割剩下的部分就是真正的Portal。
第1 步和第3 步都没有什么问题,而第2 步却是一件很麻烦的事情,那些多余的Portal
就是从这第2 步里来的。这就是我们下面要研究的问题。
如何确定当前的这个Portal 连接的是哪两个叶子?
首先考虑最简单的情况:
PDF created with pdfFactory trial version www.pdffactory.com


左边是原始的场景,右边是经过BSP 分割后的场景,红色是分割面,当我们为这个分
割面进行Portal 的生成时由于这个节点的front,back 子树都是叶节点(A 和B)所以可以
很直观的知道这个Portal连接的是A和B 这两个叶节点。‚里也是这样做的。
下面考虑复杂一点的情况:


这个场景先被分割面1 分割,分割后的右半部分又被分割面2 分割。假设现在正在为
N0 进行Portal的生成。因为front子树是叶节点,所以可以知道Portal 一定连接了A,不过
back子树不是叶节点,所以我们只知道另一边连接的是N1 但却不知道具体是N1 下的哪个
叶节点。但是我们可以发现N0 与N1 的分割面是平行的,这个时候我们可以比较这两个分
割面的位置,因为1在2 的前边,所以Portal 连接的另一个叶节点一定在分割面2的前边,
也就是N1 的front 子树里,所以我们知道Portal 连接了N1 的front 子树。对于这个例子,
在下一次的判断中因为发现B是叶节点,所以得出Portal 连接了B。‚里也是这么做的,如
果两个分割面平行则可以进行进一步的判断。
下面考虑不平行的情况:


PDF created with pdfFactory trial version www.pdffactory.com
场景先被1分割,分割后右边的部分又被2 分割。在为1 生成Portal的时候知道它连接
了A。但是另一边呢?答案是不知道。那‚里边是怎么做的呢?答案是它把Portal 拆成了两
个,一个连接A和B,一个连接A 和C。
多余的Portal 产生了。
但有的时候这样做不会有问题,甚至是必须要这么做。


上面这种情况会产生2 个Portal,一个连接A 和B,一个连接A和C。而这是正确的。
现在可以对‚的方法进行一下总结,如果front,back 子树都是叶节点,我们可以知道
Portal连接了哪两个叶节点。否则我们只能把这个Portal拆成两个,而这会产生多于的Portal。
但是‚通过以下几点来减少多余的Portal:
1. 如果两个分割面平行则可以进行进一步的判断。
2. 有些时候这样做的结果是正确的,不会产生多余的Portal。
3. 在生成Portal的第3 步会对Portal 进行切割,因为多余的Portal 都是错误的Portal所以有
些多余的Portal 会在切割时被切割掉,也就是切割没了。如下图:


PDF created with pdfFactory trial version www.pdffactory.com
假设在为分割面1 生成Portal 的时候产生了一个多余的Portal,它连接的是A和另一边
的某个叶节点X。在用A 和X 对其进行切割的时候会把它切没。
如何去除多余的Portal?
就像‚里边所说的那样,需要在算法之后加入一个专门去除多余Portal的过程。但是如
何判断一个Portal是不是正确的呢?(多余的Portal都是不正确的)。
观察BSP 树中的Portal 可以发现它与它所连接的那两个cluster 都是紧密的连接在一起
的。换句话说就是Portal所连接的那两个cluster中都必然存在位于Portal所在平面上的顶点。
这一点可以通过BSP室内场景“凸”和“闭和”的建模限制来保证。
因此第一个检测条件是检测Portal连接的那两个cluster中是否都存在位于Portal所在平
面的顶点。如果不是则这个Portal 是一个错误的Portal,也就是多余的Portal。在程序中我
们要做的是对自动生成的每一个Portal 遍历它所连接的那两个cluster 中的顶点,检测这些
顶点与这个Portal 所在平面(也就是分割面)的位置关系,如果某个cluster 中不存在位于
Portal所在平面上的顶点就把这个Portal 去掉。
那么只有这一个条件是否足够呢?考虑以下这几种情况:


虽然它们存在与位于Portal 所在平面上的顶点,但是不会出现这种情况,因为在生成
Portal时那个多余的Portal 就已经被切割没了。


PDF created with pdfFactory trial version www.pdffactory.com
虽然它们存在与位于Portal 所在平面上的顶点,但是这样的场景简直无法理解,虽然它
能够建成一棵BSP树并在这两个cluster“重叠”的地方生成一个Portal,但是我相信不会有
美工做出这种东西来的。


上边那个图的Protal会在一开始被切割没。
下边那个图没有意义。


Protal 会在一开始被切割没。


这三个图都违反了建模约束。
由上边的例子可以看出使用这个条件来去除多余的Protal是可行的。

原创粉丝点击