1. 程式人生 > >NavMesh生成研究(一):體素化過程

NavMesh生成研究(一):體素化過程

NMGen是一個開源專案,包括Java版的recast靜態網格生成程式碼,以及詳細介紹生成過程的文章。因為在閱讀過程中覺得對理解recast原理非常有用,所以決定將其翻譯在自己blog上。

原blog上完整的目錄包括:

其中第一篇第二篇已經由遊藍海做了翻譯。這裡從第四篇開始,分步驟詳細講述NavMesh的生成過程。翻譯時力求忠實於原意,且儘量通俗易懂。譯文如下:

概述

構造導航網格的第一步是使用體素化(voxelization)建立實心高度域(solid heightfield)。

如果你需要回憶體素化的執行過程,請回到總體概述

建立實心高度域

當我們建立了源網格(source mesh)的AABB包圍盒和容納體素資訊的實心高度域後,為每個源網格中的多邊形執行下列操作:

確定多邊形在高度域格子上的投影(footprint)——也就是多邊形的AABB包圍盒在2D座標系下的投影。因為求取多邊形投影覆蓋的格子需要交集測試,這樣做的好處是可以降低交集測試的數量。

這裡寫圖片描述

遍歷投影覆蓋的所有高度域格子列(grid column),並求出源多邊形與列相交的比例。如果出現一次相交,那麼得到一個新的“裁剪過的”(clipped)多邊形。然後確定這個多邊形的最低和最高的高度。這就代表著格子列被源多邊形佔據的比例。

這裡寫圖片描述

我們基於以下資訊來為高度域新增區間(span):

  • 與多邊形有交集的格子列
  • 裁剪得到的多邊形的最低和最高高度範圍(格子列被佔據的比例)
  • 裁剪多邊形的表面是否可行走(traversable)

其中最後一條資訊取決於源多邊形在y軸的傾斜度(slope)和配置的maxTraversableSlope屬性值。如果前者小於後者(例如45度),那麼表面可行走。

當新的區間資料新增到高度域時,會做如下事情:

如果新的區間不與任何現存的區間相交,那麼建立一個新的區間。否則合併兩個區間。

當兩個區間合併時,必須驗證合併後的區間是否可經過。可行走標誌(traversable flag)只應用在區間的上表面。如果設定了該標誌,那麼就意味著區間的頂端多邊形有較低的傾斜度,因此可行走。

如果新區間的頂端高於要合併到的區間頂端,那麼將新區間的可行走標誌應用到合併後的區間上。

如果新區間的頂端低於要合併到的區間頂端,那麼我們不用關心新區間的可行走標誌,直接丟棄。

如果新區間的頂端與要合併到的區間高度一致,那麼只要兩者中任何一個可行走,那麼合併後的區間也是可行走的。

這裡寫圖片描述

更多的高度域區間標誌

技術上來說,源網格的體素化已經完成,而且高度域已包含佔據空間的實心體素區間。區間也有標誌代表頂端表面是否可行走。但是這個標誌的設定只考慮了與區間相交的多邊形的傾斜度。現在是時候做更多的過濾了:從一些區間上移除可行走標誌。

兩種型別的過濾:

首先,當區間上方有非常近的障礙物時,它的頂端表面也不可行走。想象地板上的一張桌子。雖然桌子下面的地板是平坦的,但仍然不可行走(因為容納的高度不夠)。

這裡寫圖片描述

一個可選擇的過濾與凸起(ledge)檢測有關。如果從區間的頂端到相鄰的區間下降的距離超過了一定閾值,那麼這個區間被認為是個凸起,也不可行走。

這裡寫圖片描述

目前的進展

在這一步結尾,我們構造了一個代表源網格佔據區域的高度域。執行初步的過濾後,佔據區域的頂端表面被標記為是否可行走。