Navigation Mesh與Line-of-Sight Test


LOS_1.png

上圖是一個由任意凸多邊形構成的導航網格,白線包圍區域代表着不可進入的障礙區域,紅線包圍區域則可以進入或穿越。網格中所有多邊形的頂點存儲次序均爲順時鐘序。在下面的討論中,我們的運算一概採用左手系進行。

假設當前所處的位置爲p0,視線方向矢量爲n0,p0位於多邊形A中,我們知道每一條邊的兩側的多邊形的編號,現在的問題是:如果求得該視線途經了哪些多邊形?與這些多邊形的哪些邊相交於何處(即Way point)?該視線終結於哪條邊的何處?

首先讓我們來解決一個子問題,即判斷射線r與某凸多邊形p之間的關係。不難想象,r只可能與p不相交、相交於1點或2點(只有穿出、或先射入後穿出)。這裏我們最關心的是:(1) r究竟與p相交否?(2) 如果相交,那麼r穿出p時,其交點在哪條邊上?在哪裏?

以A和射線r=(p0,n0)爲例,先來判斷A與r是否相交,這個太容易了,只需判斷A有沒有邊與r相交即可。遍歷A的每一條邊e,然後得到每一條邊的起點和終點(注意,時刻牢記頂點順序是順時鐘的)。然後,分別獲得起點矢量from和終點矢量to,然後計算test_a=from×n0和test_b=to×n0,再來檢查test_a和test_b的Z分量符號:如果相同,則from、to均位於n0的同一側,e與r不相交;如果test_a.Z>0且test_b.Z<0,則e爲射線r在A中的穿出線;如果test_a.Z<0且test_b.Z>0,則要麼e是射線的反方向與A的交線,要麼e爲射線在A中的射入邊。這裏,我們最關心的是有沒有test_a.Z>0且test_b.Z<0的情況,即有沒有穿出邊。

如圖,如果要對r進行LOS test,首先我們要判斷一下p0處於哪個多邊形,這個點與多邊形關係的判斷也很容易,這裏,我們的p0位於A中。然後,在A中找射線r的穿出邊和穿出點(求兩射線的交點,trivial),判斷穿出邊的另一側的多邊形是否可以進入?如果是障礙或網格邊緣,則LOS test中止,如果不是,則獲得穿出邊另一側的多邊形編號,這裏是B,然後繼續在B中找射線r的穿出邊和穿出點,繼續前面的一系列步驟,直到找出r的所有途經多邊形、所有穿出邊和穿出點爲止。以上便是一次完整的視線檢測過程。是不是足夠簡單?heh
 
如何判斷點p0是否處於凸多邊形內?

LOS_2.png

見上圖,這裏我們採用叉乘法,雖說只適用於凸多邊形,不過計算最簡便,不涉及三角運算(內角和法)和開方(面積法),什麼水平垂直交叉線檢測就直接免了吧,too ugly。假設多邊形是順時鐘頂點序,我們採用的是左手系。遍歷每條邊,作一個邊矢量e,從起點到終點;然後作測試矢量t,從邊起點到要測試的點p0;計算test=e×t,如果test矢量的Z分量符號始終保持不變,則p0處於多邊形內部;一旦其符號發生了改變(只需檢測到一次符號改變即可),則p0處於多邊形外部。

導航網格和LOS檢測用來幹什麼的?

導航網格一般用來做層級式A*尋徑,它可以很容易地推廣到3D路徑規劃,與某些附加特性相配合,能夠實現更多的特殊用途;LOS檢測主要有兩個用途:動態局部Point of View尋徑和A*路徑優化(平滑+Cutting the Corner)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章