二元空間分割樹 BSP (二)

2021-06-26 15:09:00 字數 2772 閱讀 9581

來自於:

在渲染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

二元樹的深度

題目 輸入一棵二元樹的根結點,求該樹的深度。從根結點到葉結點依次經過的結點 含根 葉結點 形成樹的一條路徑,最長路徑的長度為樹的深度。例如 輸入二元樹 10 614 412 16 輸出該樹的深度3。二元樹的結點定義如下 struct sbinarytreenode a node of the bin...

C 中二元函式物件和二元謂詞

在c stl演算法中,在演算法的輸入和輸出中,一定要分清是函式物件,還是謂詞,還是迭代器。具體看如下 注意看注釋 includeusing namespace std include string include include include include include 二元函式物件 temp...

python選擇排序二元選擇 二元選擇排序

注 本題只需要提交標記為修改部分之間的 c 語言方式。二元選擇排序 對傳統的選擇排序演算法改進,在一趟比較過程中,同時記錄最大值和最小值位置,將最小值與第乙個元素交換,最大值與最後乙個元素交換,即一趟比較確定兩個元素,對剩下的序列重複上述過程,直至序列為空。include using namespa...