來自於:
在渲染3d遊戲的室內場景時,bsp樹是往往是乙個比較複雜但非常有效的方法。它可以用來進行高效的深度檢測。深度檢測通常
用來決定哪個物體離視點更遠,然後再根據從遠到近進行多邊形繪製,這樣出來的結果才是正確的。
首先給出乙個圖,我們可以看出在removal b區域,白色的多邊形覆蓋了黃色多邊形,而在removal a區域,黃色多邊形覆蓋了白色區域,如果沒有深度檢測,我們可能看到在removal a和removal b兩個區域都是黃色多邊形擋住了白色多邊形,這和實際情況相違背。所以深度檢測非常重要。
opengl直接提供了深度檢測,但是它的效率很低,因此我們還是要考慮使用bsp樹來解決問題。bsp樹將多邊形快速排序,並以樹的形式儲存,它的讀取非常有效,可以在執行時快速地找到哪個多邊形離視點最遠。
在這個場景中,黃色字母代表牆壁,粉紅色圓代表視點位置,虛線代表視線範圍。
這個場景顯然需要深度檢測,否則a和f可能會擋住d,b和e, 這是不可接受的。我們需要建立一棵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...