從零開始學(xué)習(xí)導(dǎo)航網(wǎng)格#7 recast代碼分析之solomesh(中)

上回說到將空間內(nèi)的span都打上了區(qū)域標(biāo)記
到目前為止,可行走區(qū)域都是以span為粒度表示的(一個(gè)一個(gè)的小方格),現(xiàn)在我們要根據(jù)區(qū)域標(biāo)記來合并這些“小方格”,形成整片的連續(xù)區(qū)域

Step 5. Trace and simplify region contours.

a.遍歷緊縮高度場中的span,根據(jù)regid(區(qū)域標(biāo)記)求出每個(gè)span與周圍相鄰span的區(qū)域關(guān)系,用一個(gè)4位的2進(jìn)制數(shù)來表示:
若與某個(gè)方向的鄰居區(qū)域相同,則對(duì)應(yīng)的標(biāo)記記為0,這樣最后得到的flag若為0,則表示是一個(gè)區(qū)域內(nèi)部的span(4面都是自己人),否則就是一個(gè)區(qū)域邊界上的span
這樣處理完之后,就明確知道了哪些span是區(qū)域的邊界

這里要特別區(qū)分一個(gè)咬文嚼字的問題:
“區(qū)域的邊界”和“邊界區(qū)域”是兩個(gè)不同的概念。邊界區(qū)域在recast中的定義為:
the region is a border region and its spans are considered unwalkable.
是整個(gè)包圍盒外面的4塊區(qū)域,被認(rèn)為是不可行走的


邊界區(qū)域

b.遍歷所有作為區(qū)域邊界的span,在遍歷的過程中得到區(qū)域邊界的輪廓頂點(diǎn)集
具體流程是這樣的:
以一個(gè)邊界span作為起始位置,順時(shí)針方向判斷它的4條邊:
若當(dāng)前邊是區(qū)域分界邊,則將邊的一個(gè)頂點(diǎn)加入到輪廓頂點(diǎn)集中,并繼續(xù)判斷下一條邊
若當(dāng)前邊不是區(qū)域分界邊,則移動(dòng)到與這條邊相鄰的span中(這個(gè)span是在同一個(gè)區(qū)域內(nèi)),重新判斷新的span的邊

walkContour

具體的實(shí)現(xiàn)在這個(gè)函數(shù)中

static void walkContour(int x, int y, int i,
                        rcCompactHeightfield& chf,
                        unsigned char* flags, rcIntArray& points)

rcIntArray& points是輸出的輪廓頂點(diǎn)集,每個(gè)元素是一個(gè)四元組:(x,y,z,r)
特別注意這里的第四個(gè)參數(shù),r表示對(duì)應(yīng)的鄰接區(qū)域id以及一些附加細(xì)節(jié)信息(是否是邊界區(qū)域的頂點(diǎn)、是否是區(qū)域邊界頂點(diǎn))

頂點(diǎn)的xz坐標(biāo)好處理,高度值y的計(jì)算是通過這個(gè)函數(shù)

static int getCornerHeight(int x, int y, int i, int dir,
                           const rcCompactHeightfield& chf,
                           bool& isBorderVertex)

它做的事情是考慮以一個(gè)頂點(diǎn)為中心的4塊相鄰格子的span,取這4個(gè)span中高度最高的span作為頂點(diǎn)高度
(注意下圖是一開始的實(shí)心高度域,鐵子們自行腦補(bǔ)一下緊縮高度域)


計(jì)算頂點(diǎn)高度

c.執(zhí)行完walkContour后就得到了輪廓頂點(diǎn)集,但是這個(gè)集合中的點(diǎn)可能非常多(區(qū)域是基于體素的粒度,所以現(xiàn)在的邊是由許多長度為體素格子邊長的短邊拼接成的)
所以需要簡化輪廓線

有兩個(gè)頂點(diǎn)集:
rcIntArray points 原始輪廓頂點(diǎn)集合
rcIntArray simplified 簡化頂點(diǎn)集合(需要保留下來的點(diǎn))
簡化的策略是:
首先不同區(qū)域的過渡點(diǎn)需要保留,放到simplified中
然后對(duì)于simplified中的每個(gè)相鄰點(diǎn)對(duì)(假設(shè)記為AB),檢查points中位置在AB之間的點(diǎn),若這些點(diǎn)到AB的距離大于某個(gè)值maxError
則將其中距離最遠(yuǎn)的點(diǎn)加入到simplified中,重復(fù)這個(gè)過程直到所有點(diǎn)距離簡化的輪廓線都不超過maxError


簡化輪廓線

至此我們就將體素方格化表示的可行走區(qū)域轉(zhuǎn)化成了由頂點(diǎn)集合表示

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容