二元空间分割树(BSP)(二)

二元空间分割树

作者:Paul Frazee (The Rainmaker),译者:Cater.Chen

来自于:http://nehe.gamedev.net

在渲染3D游戏的室内场景时,BSP树是往往是一个比较复杂但非常有效的方法。它可以用来进行高效的深度检测。深度检测通常

用来决定哪个物体离视点更远,然后再根据从远到近进行多边形绘制,这样出来的结果才是正确的。

首先给出一个图,我们可以看出在Removal B区域,白色的多边形覆盖了黄色多边形,而在Removal A区域,黄色多边形覆盖了白色区域,如果没有深度检测,我们可能看到在Removal A和Removal B两个区域都是黄色多边形挡住了白色多边形,这和实际情况相违背。所以深度检测非常重要。

OpenGL直接提供了深度检测,但是它的效率很低,因此我们还是要考虑使用BSP树来解决问题。BSP树将多边形快速排序,并以树的形式保存,它的读取非常有效,可以在运行时快速地找到哪个多边形离视点最远。

在这个场景中,黄色字母代表墙壁,粉红色圆代表视点位置,虚线代表视线范围。

这个场景显然需要深度检测,否则AF可能会挡住D, BE, 这是不可接受的。我们需要创建一棵BSP树,其过程如下:

1) 编写一个函数,在所有多边形中选择一个多边形(所有多边形作为函数参数)

2) 将多边形转化为平面

3) 根据函数判断并分类出多边形位于平面的前面、后面、重合、穿越

4) 对穿越平面的多边形进行分割

5) 如果存在前向多边形,跳转到步骤1),传递这些前向多边形作为函数参数

6) 如果存在后向多边形,跳转到步骤1),传递这些后向多边形作为函数参数

7) 将重合的多边形加入到树的顶点列表中

你或许对次算法比较疑惑,那么让我们一步步来看,注意函数的参数是一个多边形列表,如果你要选择一个多边形,需要将所的多边形传递给函数

在第一步中,我们选择一个多边形(基于某种算法或者随机选择)并执行分割。

在本例中,我们选择多边形B.第二步,我们将多边形转化为一个平面,注意平面是无限大的。

现在我们有了一个平面B. 第三步,我们将所有的多边形进行分类,在下图中,一个黄色的后向多边形,一个紫色的前向多边形,一个绿色的穿越多边形,还有一个蓝色的重合多边形。

在分类上述多边形时,我们对每个多边形通过平面方程计算其到平面B的距离,并根据此距离对多边形进行分类。

第四步,需要我们对穿越的多边形进行分割,经过分割后,结果看起来是这样子的:

后面的步骤很简单了,第五步和六步需要我们对前向和后向多边形进行递归执行,但是递归总得有个结束的过程,因此最后一步需要添加退出递归的条件,即当多边形为重合时,将它加入到当前的多边形列表。

OK,现在执行了第一次分割,看看结果:

Node 1 (Partition B): B

|

Back: Cb, A, Fb---------Front: Ca, G, D, E, Fa

好,我们再来看看对前向多边形进行的第二遍分割。

这一次我们使用多边形D进行分割,经过分类与分割得到:

这时,BSP树变成了:

Node 1 (Partition B): B

|

Back: Cb, A, Fb---------Front (Partition D): D

|

Back: Ca,Gb---Front: Ga,E,Fa

不断的分割,最后得到:

Node 1: B

|

Back: A----------------Front: D

| |

Front: Cb Back: Ca--------Front: E

| | |

Front: Fb Front: Gb Back: Gaa---Front:

Gab

|

Front: Fa

分割完毕!我们得到了11个结点,每个结点都是父结点分割而来。现在我们比较疑惑的是它到底有啥好处呢?事实上,看起来

这里所作的工作仅仅是分割了一些多边形而已。

但这恰恰是渲染时所用到的,当渲染时,我们根据视点和平面的相对位置,并根据距离渲染BSP树中的结点。从结点B开始,执

行了以下几个步骤:

1) 求解视点到平面的距离

2) 如果距离大于0:

a. 遍历后向结点,跳转到步骤1)

b. 绘制当前多边形结点

c. 遍历前向结点,跳转到步骤1)

3) 如果2)结果为false:

a. 遍历前向结点,跳转到步骤1)

b. 绘制当前多边形结点

c. 遍历后向结点,跳转到步骤1)

这就是全部工作,根据视点位置进行渲染时是按如下顺序遍历的:

A, Cb, Fb, B, Fa, Gab, Gaa, E, Gb, Ca, D


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值