二叉空间分割(BSP)树(转)

二叉空间分割(BSP)树
BSPBinary Space Partition)表示二叉空间分割。使用这种方法可以使我们在运行时使用一个预先计算好的树来得到多边形从后向前的列表,它的复杂度为 8bbb12d1070830de562c844b.jpg。它是由Fuch和Kedem在1980年首先提出的。它的基本思想是基于这样一个事实,任何平面都可以将空间分割成两个半空间。所有位于这个平面的一侧的点定义了一个半空间,位于另一侧的点定义了另一个半空间。此外,如果我们在任何半空间中有一个平面,它会进一步将此半空间分割为更小的两个子空间。我们可以使用多边形列表将这一过程一直进行下去,将子空间分割得越来越小,直到构造成一个二叉树。在这个树中,一个进行分割的多边形被存储在树的节点,所有位于子空间中的多边形都在相应的子树上。当然,这一规则使用于树中每一个节点。
我们来看一下图7.21种的多边形。为了简单起见,我们选择一个这样一个平面投影,在它上面,所有多边形都能映射为直线段。让我们由多边形B开始构造一个BSP树。(见图7.21)

多边形B所在的平面将空间分割为两个部分,使得多边形D和E位于同一个半空间中,多边形C在另一个半空间中。在这个例子中, 多边形A穿越了两个半空间,这样,它就不能十分明确的被分配到任何一个半空间中。但是,如果我们将这个多边形从它与分割平面相交的地方分为两个部分一个命名为 c69e372e7aea595d4ec22654.jpg,另一个命名为 e0774b435821701c9213c655.jpg,这样, 601d80220ddacefed6cae256.jpg就和D、E在同一个半空间中,b3597522369fe2a94723e857.jpg和C在同一个半空间中。下图表述了这一过程。

e997a43e5ff5f1f7838b137a.jpg

图7.22 建立BSP树的一个阶段

我们现在已经将问题分成了两个子问题。我们可以在子树中再次使用上述算法。例如,我们在左边子树中选择E作为分割多边形,在右边子树中选择 a1723e972a38ff6054fb9650.jpg作为分割多边形。这样,我们将建立下面的结构树。(见图7.23)

26c7cc3f975666cf7c1e717b.jpg

图7.23 建立BSP树

必须注意,任何给定的BSP树都不是唯一的。我们可以对同样的多边形找到多个有效的二叉分割。依靠我们选择来进行分割的多边形的顺序,可以得到不同的树。例如,在图7.24中,我们可以看到另一个树,它也建立在前面我们讨论的多边形上。

b35975223689e2a94723e845.jpg

图7.24 另一种结构

尽管所有适合这种算法的正确的树都可以用来得到多边形从后向前的顺序,但是总有一些要比其他一些更加有效。我们首先检查树遍历算法,然后检查确认特殊树结构的原因。
我们考虑一个包含了一系列多边形的场景, 场景带有一个预先计算好的BSP树和一个位于场景中某个位置的观察者。(见图7.25)

29b6cf2af09de720d52af146.jpg

图7.25 用BSP树来得到从后向前的顺序

我们检查观察者的位置和位于树顶部的多边形之间的关系。很明显,当这个多边形将空间分割为两个部分时,观察者必须位于其中的一个半空间中。当然,位于同一半空间中的多边形要比另一半空间中的多边形离观察者更近。基于这样的事实,如果我们首先将较远处半空间中的多边形放置在最终的列表中,然后放置根多边形,再放置与观察者在同一半空间中的多边形,这样就很容易得到多边形从后向前的顺序了。我们对每一个子树都重复同样的过程,在每一个级别中选择相应的顺序,最终,就会得到正确的多边型的顺序。
这一算法的一个优点就是无论观察者位于场景中的什么位置,无论观察者的朝向如何,它都可以很好的进行工作。例如,在图7.25 (a)中产生的列表就与(b)中产生的不同。但是他们对于各自的情况都是正确的。这样,如果我们预先为一个多边形模型计算一个BSP树,那么在运行时,我们只需要根据观察者的位置调用这个树,执行树遍历过程,就可以产生用于隐面消除的画家算法所需的从后向前的多边形顺序。
在这个算法中,在树的每一个节点处所作的判定,都依赖于观察者位于该节点多边形所产生的哪一个半空间中。在第五章中,分析平面方程式时我们已经遇到过要使用这种计算的情况。利用我们所讨论过的事实,我们可以看到,如果将观察者位置的坐标代入给定多边形的平面方程式中,结果数值的符号如果是正号,就表示观察者位于该多边形的法向量所指向的半空间中,负号表示位于另一个半空间中, 0值表示他位于这个多边形所在的平面上。最后一种情况,对于遍历整个BSP树的意图来说,意味着半空间在屏幕上的投影不相交, 并且我们可以在这一阶段的遍历过程中选择任何子树的顺序。
相同的计算也要在预先计算一个BSP树时使用到。我们需要决定不同的多边形应该被放置在哪个子树中。从可实现性的观点出发,预先计算一个BSP树的过程可以被描述成下面的形式:对多边形集合,我们选择一个多边形。进一步计算该多边形的平面方程式。对剩余的多边形,我们用所说的方程式检查它们的所有顶点。如果所有顶点都是负值,那么多边形就放置在一个子树中;如果都是正值,那么多边形就放置在另一个子树中;如果结果有正有负,那么多边形就被分为两部分,分别放置在两个子树中。一旦我们将所有多边形分配到了正确的半空间中,我们就可以对子树进一步调用同样的方法来进行处理,直到当前的子表只包含一个多边形为止。
一个多边形被任何平面所分割的问题可以当作一个裁剪问题来处理。解决这一问题的算法只与我们在裁剪问题时所讨论的算法又很小的差别。唯一明显的差别就是在二进制搜索边缘裁剪过程中,我们将使用分割多边形的平面方程式来找到边的中点的位置。

278563cb89833012bf09e647.jpg

图7.26 使用BSP树渲染的一个场景,左边是不同的多边形

对于垂直边的裁剪情况,我们使用二分搜索技术,根据边的中点的位置抛除掉边的一部分。既然这样,我们可以使用类似的方法来进行处理,区别只是改变一下判据。我们可以将同样的方法用于多边形的裁剪。
应该强调的是,由于一个BSP树的结构是预先确定的,因此我们不必担心建立树时算法的效率问题。
一旦创建了树,要得到多边形从后向前的顺序,就要采取下面的步骤:我们取位于树顶的一个多边形。计算这个多边形的平边方程式。将观察者当前的位置坐标代入方程式中,观察结果的正负号。接着对子树运用相同的方法
进行处理。
我们回忆一下平面方程式的形式:

b2e8c133e252134eac4b5f40.jpg

式中,P表示平面中的点, bbb4e3ed9facc14279f05541.jpg时平面的法向量。它还可以表示成下面的形式:

5f8c6131309c7114eac4af43.jpg

后一种形式是通过对原始形式进行标量相乘得到的,使得 417a2bfa72416413a9d3114c.jpg7dfed313a99fcb2edc54014d.jpgeb9ab56eca0993d780cb4a4e.jpg

225416f40e1b6f63dcc4744f.jpg。当我们在视空间中遍历整个树时,观察者的位置为(0,0,0),我们提到的代换结果等于平面方程式中的系数D。这样,BSP树遍历可以很方便的在透视变换之前来进行。
表7.1显示了一个树遍历的结构。

9b2f14330d8b29f51b4cff49.jpg

表7.1 遍历一个BSP树

我们考查了树的创建和遍历之后,仍然有一些问题需要解决。当我们构建一个树时,我们可以选择剩余多边形中的任何一个来分割空间。选择不同的多边形会导致不同的树的结构。因此,我们就应该考虑选择哪个多边形有助于算法的效率。
有些多边形会导致剩余多边形更多的分割(见图7.21、7.23和7.24)。每一个多边形在通过渲染管道时都有一定的系统消耗,因此多边形越少,性能就越好。我们可以利用判据来选择有较少分割的多边形。
使用判据来平衡BSP树,并不需要每一级中的子树中的多边形的数量都相同, 因为它不会影响运行时间。树的遍历总是假设至少每次都取一个多边形,因此平衡不会影响性能——我们仍然不得不每次取每一个多边形。另一方面,一个平衡的树可以以较少的迭代调用来执行遍历。我们可以将平衡作为第二判据来使用。
总之,使用BSP树来进行从后向前排序的最大优点就是算法运行的复杂性较低 。这种方法也解决了多边形的多重交叠和多边形穿越问题。但是,通过使用一个预计算结构,我们已经失去了一定的灵活性。如果多边形的排列在运行时发生了改变, BSP树就必须发生相应的改变。由于计算量非常巨大,我们不能这样做,因此,这种算法对于场景在运行时发生改变的情况就不能使用了。
应该注意,只有当多边形经历不同的变换设置时树才会受到影响。如果所有的多边形都使用同样的变换,那么分割仍然是正确的,树也将不会受到影响。这样,场景中的一个动态物体,它在世界中移动或者是旋转,仍然可以使用同样的BSP树。如果物体中的一部分相对于其他物体发生了移动,那我们就要使用其它的算法了。

1b8baf457d17402bcefca378.jpg

图7.21 一个二叉空间分割

转载于:https://www.cnblogs.com/wanghao111/archive/2009/06/11/1501062.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值