dtNavMeshQuery::findLocalNeighbourhood m_tinyNodePool->getNode dtHashRef整数哈希 getPortalPoints dtOverlapPolyPoly2D

dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius, const dtQueryFilter* filter,

dtPolyRef* resultRef, dtPolyRef* resultParent, int* resultCount, const int maxResult):

 

 

先把startNode加入stack

把startNode加入resultRef中

 

While(stack不空)

{

    dtNode* curNode = stack[0];出队列

    获得curTile和curPoly

    遍历curPoly的所有link

    {

        根据link->ref获得neighbourRef

        neighbourNode = 在m_tinyNodePool 中getNode

        如果找到了则返回这个node,如果没有找到就分配一个node

        如果这个node已经DT_NODE_CLOSED访问过了,则continue

        然后获得neighbourTile, neighbourPoly

        如果neighbour是offmeshconnection,或者不能passFilter,则continue

 

        getPortalPoints获得两个polygon的portal    va   vb

        dtDistancePtSegSqr2D (centerPos, va, vb, tseg);算出centerPos到va,vb的距离,也就是到neibour的距离

        这一步,centerpos的y轴是有影响的

        如果距离超过了radiusSqr,则continue;

 

        neighbourNode设置为DT_NODE_CLOSED,且其pidx设置为当前node

       

 

接下来检查这个neighbourPoly是否与我们已经找到的polygon重叠

Pa记录neighbourPoly的顶点

从resultRef中掏出所有的polygon

{

先判断是否跟curPoly连接,如果连接则说明肯定不是重叠的

    否则把这个polygon的顶点放在pb里面

    dtOverlapPolyPoly2D(pa,npa, pb,npb) 判断是否重叠

这一步因为是映射到了xz平面所以y轴的值是没有影响的

}

if (overlap) continue;

        否则 放入resultRef

        放入stack中

    }遍历curPoly的所有link结束

}stack空

最多找到的结果不能超过maxResult个,超过了就返回status |= DT_BUFFER_TOO_SMALL

 

总之就是:一个一个node进队列,找neighbour,直到都超过距离了,队列空了为止,或者超过了设置的上限。

 

 

 

=========================================================================================

 

m_tinyNodePool->getNode

通过dtHashRef算出bucket

在m_first哈希表中找到m_Nodes的坐标

m_nodes[i]中记录的id和state都对应上了,就是找到了

否则在m_next[i]获得m_nodes中的下一个位置

找到了就返回,找不到的话这个i就是我们要插入node的位置

其实就是对m_nodes[i]进行init

然后

m_next[i] = m_first[bucket];

    m_first[bucket] = i;

相当于插在了链表的最前边

 

 

=====

 

dtHashRef整数哈希?

https://www.cnblogs.com/napoleon_liu/archive/2010/12/29/1920839.html

目的: 1. 函数要是可逆的(1对1的映射) 
       2. 雪崩效应(输入中1bit的变化 影响 输出中1/4 到 1/2的bits变化)

 

可逆靠的是可逆操作:

key + const_value 加法是可逆 
    key - const_value 减法是可逆 
    key ^ const_value 异或是可逆的 
    ~key 取反也是可逆的 
    key * const_value 乘以一个奇数也是可逆的

 

 

 

====

getPortalPoints (dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile,

dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile, float* left, float* right):

 

从fromPoly的每一个link开始找,如果ref是toPoly,就是找到了

找不到说明参数错了

 

如果fromPoly是offmeshconnection那么找到ref对应的to的边的两个点存在left和right

如果toPoly是offmeshconnection那么找到ref对应的from的边的两个点存在left和right

否则就是用之前找到的link获得两个点赋给left和right

 

最后,如果if (link->side != 0xff)是tile的boundry

用link->bmin和link->bmax解压出插值的比例算出left和right

 

====

 

dtOverlapPolyPoly2D (const float* polya, const int npolya,

                         const float* polyb, const int npolyb):

for(polya中的所有边)

{

    根据每个边算出n[3] = { vb[2]-va[2], 0, -(vb[0]-va[0]) };

    N相当于这个边在xz轴上投影,然后垂直

    把n当成轴,进行

projectPoly(n, polya, npolya, amin,amax);

projectPoly(n, polyb, npolyb, bmin,bmax);

也就是把每个边分辨在n上投影,算出投影在n轴上的整个poly的坐标amin,amax

然后overlapRange(amin,amax, bmin,bmax, eps)看两个poly投影的结果是否有重叠。但凡有没重叠的情况,两个poly肯定不想交。

}

 

 

 

与上面相同,遍历polyb

 

posted @ 2018-04-19 15:19  iceberg-liu  阅读(563)  评论(0编辑  收藏  举报