終於將HL2的vbsp,vvis看完了,隨便也翻了翻q3map代碼,發現兩者的代碼太相似了,可以看出在BSP分割,portal的尋找方面在Q2中都應該已經定型了,因此兩者使用的演算法都是一樣的。下面我主要談一下計算pvs的演算法,因為在我翻譯的那篇文章《bsp技術詳解》中計算pvs是通過在每個portal上確定一些採樣點然後進行ray cast來計算pvs的,這種方法的速度沒有保證,而且處理起來也非常麻煩。而ID通過對每一個portal的polygen進行clip的方法來擷取pvs,確實速度上要比上一個方法好上
很多。下面我來對演算法進行詳細的介紹,如果你對bsp不是很熟的話需要明確一下幾個概念,一個是cluster,對於室內情境來說它完全是由cluster組成的,簡單的你可以將它認為是情境中的一個房間,另一個是portal,情境中的cluster是由portal串連為一個整體,你可以把它看作是房間的門或窗戶。在進行pvs計算的時候已經將整個情境劃分為bsp tree,尋找完portal並將cluster和leaf node串連起來了。
1、首先對所有的portal先進行一下預先處理,讓一個portal只和一個cluster發生聯絡,這樣作的目的是為了獲得一個單向的portal,也就是說portal只在一邊可見,這樣做是為了方便進行處理。我們知道一個portal通常串連了兩個cluster,一般情況下使用的是portal所在plane正面的portal,但為了達到上述目的,我們需要將portal分為正反兩個,由於在bsp中每一個plane都儲存正反兩個,因此位於反面的portal只需要對ploygen顛倒一下
頂點順序即可。這裡規定一個portal只和位於其plane的法線方向上的luster發生聯絡,預先處理後儲存的portal數量是原來的2倍。
2、接著我們需要對portal進行一下分類處理。通過簡單的常識我們知道,由於現在每一個portal都是單向可見,因此只有位於portal可見方向(稱為front方向)的portal才可能是可見的,我們需要對每一個portal都獲得一個front portal列表並儲存起來。
3、下面我們需要進一步的對每一個portal的front portal列表中不可見的portal進行剔除。我們知道情境完全是由一個個portal串連起來的cluste組成的,對於一個portal來說位於同一個cluster的portal一定可見,而其他portal要想可見最基本的要求是它可以通過其他portal串連到這個cluster上,因此通過portal的串連關係我們可以從front portal列表中剔除那些和當前portal沒有串連關係的portal,並儲存到floodportal列表中。
4、好了經過上面的處理我們已經剔除了大部分不可見的portal,可見的portal一定包含在flood portal列表中,因此需要使用更精確的方法進行檢查。為了方便描述,我假定當前計算pvs的portal為A,任選和A所在的cluster ca相連的一個portal稱為B,注意B一定是可見,因此B所在的cluster cb一定可見,但是和cb相連的其它portal並不一定可見,為了檢查是否可見,我們假定選取其中的一個portal稱為C。好了現在的問題簡化為已知A和B求C是否可見,演算法如下:
在A上選取一條邊和B上的一個頂點構成一個clip plane,為了保證這是一個合法的clip plane我們需要做一下檢查,為了簡單化我們首先需要保證clip plane的法線方向必須指向portal A的外部,也就是說A上所有的頂點都位於clip plane的背面。
其次我們要保證portal B上所有的頂點都位於clip plane的正面,這樣做可以保證當你選擇A上最左邊的一條邊時必須要和B上最右邊的一個頂點構成clip plane,當你選擇A上最右邊的一條邊時必須要和B上最左邊的一個頂點構成clip plane,將所有的clip plane合并起來實際上就獲得一個A到B的最大可見frustum,只有位於frustum內部的portal才是可見的。當建立起這個frustum後我們就可以使用它對C的polygen進行clip操作了,當C clip後如果沒有polygen在frustum內部那麼它是不可見的,否則portal C可見並將可見的polygen儲存下來。當C可見後我們需要接著對和C相連的portal進行檢查,方法還是一樣不過上面的portal B變成了C而且必須要注意,建立frustum使用C的polygen應該是clip後的polygen資料。通過上面的方法對A的flood portal列表進行遞迴運算最終將獲得一個真正的可見portal集合儲存到vis portal列表中。還需要指出一點的是建立clip plane的過程實際上需要兩次,第一次是從A到B,第二次是從B到A,這樣做的原因是並不是所有的極值點都位於B上的,也可能位於A上因此需要進行兩次。
Q:怎麼根據AB產生Frustum?
A:如果portal A和B都是一個四邊形的話,frustum的四個面是這樣組成的,A的左邊和B的右邊構成一個plane,A的右邊和B的左邊構成一個plane,上下方向也是,這樣就形成一個frustum。但是當portal由多個頂點構成時,組成frustum的面也不會只有四個,這樣形成的會是一個多面的frustum。