在checkPathValidity(檢查所有agent的corridor的m_path是否有效)
如果是無效的要進行重新設置并且設置replan
?
首先獲得第一個polygon,m_path[0]
這里,因為addagent的時候,ag->corridor.reset(ref, nearest);
m_path[0] = ref;
所以就算是沒有設定目標,const int npath = ag->corridor.getPathCount();也是1
?
然后根據FirstPoly的polyref進行檢查,isValidPolyRef
檢查的條件是,可以獲得poly和tile,并且passfilter
如果不是有效的則:
通過findNearestPoly-> queryPolygons找到最近的poly
用其返回的距離poly的最近點覆蓋agentPos
如果沒有找到NearestPoly,設置agent的state 為 DT_CROWDAGENT_STATE_INVALID
然后ag->corridor.fixPathStart主要是給corridor的m_path[0]設置成找到的這個點
把當前agent的ag->npos設置成我們計算出來的最近點
因為初始點是被設置過了,所以要replan = true;
?
同樣的,對目標點進行isValidPolyRef檢查
如果是無效的,用上面的方法,找到一個有效的來
設置到ag->targetPos
如果最終還是找不到targetRef
ag->targetState = DT_CROWDAGENT_TARGET_NONE
?
然后檢查ag->corridor.isValid,其實就是檢查這個corridor里面的m_path的所有poly是不是isValidPolyRef,如果有invalid的,則replan = true;
?
最后 如果需要replan :r
equestMoveTargetReplan 就是設置agent的targetRef, targetPos,以及state設置成DT_CROWDAGENT_TARGET_REQUESTING
?
=========================
dtNavMeshQuery::queryPolygons(const float* center, const float* halfExtents,
??????????????????????????????? const dtQueryFilter* filter, dtPolyQuery* query):
計算center為中心halfExtents為半徑的包圍盒所觸及的tiles
在所有觸及到的tiles中執行queryPolygonsInTile
這個函數的用途就是為了對所有多邊形執行process,進而找到最近的poly
如果找到了,我們就覆蓋nearestPt
?
==============
queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax,
??????????????????????????????? const dtQueryFilter* filter, dtPolyQuery* query):
如果使用了bvtree:
{
float minx = dtClamp(qmin[0], tbmin[0], tbmax[0]) - tbmin[0];……
把center為中心halfExtents為半徑的包圍盒轉換為這個相對于這個tile原點的相對位置
Bmax確保比bmin大1
接下來遍歷bvtree,從數組中的第一個node開始,計算是否覆蓋,
node->i如果大于零說明是葉子,表示其在本tile中的poly序號,否則就表示跨過多少個找其右邊的兒子
接下來:
1 如果是葉子并且相交了并且通過了passfilter,記錄下來這個node,這個node是一個polygon
如果記錄的總數已經到達了batchSize的上限了則process,主要就是找到最近的點和最近的多邊形,batchSize是一個批次的量,也就是說是按照批次進行處理的。
2 如果是葉子但是沒有相交或者不是葉子但是相交了,那就node++,走下一個樹根或者走當前樹根的第一個節點
3 如果既不是葉子也沒有相交,那就可以跨過去當前這個樹根了,直接跨過-node->i個節點。
}
?
如果沒有使用bvtree:
For(這個tile里面的所有polygon)
{
??? 不可以是offmeshconnection并且必須passFilter
??? 求出多邊形的AABB
??? 然后跟使用bvtree的情況下一樣找到最近的點和最近的多邊形
}
?
最后把沒有滿一個批次的,調用process進行處理。
?
?
=====================
dtFindNearestPolyQuery :: process(const dtMeshTile* tile, dtPoly** polys, dtPolyRef* refs, int count):
For(每一個poly)
{
??? 計算m_center跟這個poly的最近點,dtNavMeshQuery::closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest, bool* posOverPoly):
??? 通過dtDistancePtPolyEdgesSqr(pos, verts, nv, edged, edget)計算出,pos對于每條邊的最近距離,并且存在edged里面,函數返回值表示點是否在多邊形內部。
??? 找到距離最小的那條邊的兩個頂點va,vb
dtVlerp(closest, va, vb, edget[imin]); 根據edget對va,vb進行插值,求得多邊形上距離pos最近的點closest
edget里面存的是 http://blog.sina.com.cn/s/blog_5d5c80840101bnhw.html 這里面的r
因為且
?
所以可以用r來作插值計算closest的坐標。
?
?
posOverPoly記錄是否在多邊形內
接下來計算m_nearestDistanceSqr,存的是點與這些多邊形的最短的直線距離。
有一個情況除外,就是在posOverPoly的情況下,計算的是y軸的距離,如果比walkableClimb小的話,直接就選它了,否則就是記錄高度距離的平方存在nearestDistanceSqr
然后找到距離最小的點,存在nearestDistanceSqr
}
?