dtNavMesh::addTile connectIntLinks baseOffMeshLinks connectExtOffMeshLinks connectExtLinks ...

dtNavMesh::addTile  connectIntLinks  baseOffMeshLinks  connectExtOffMeshLinks connectExtLinks  connectExtOffMeshLinks


dtNavMesh::addTile(unsignedchar*data,intdataSize,intflags,

                            dtTileReflastRef,dtTileRef*result)

 

data包含了header的信息,可以通过header->x,header->y,header->layer找到一个tile

getTileAt

如果能找到则不能再addTile了

否则:

 

 

if (!lastRef)

{

    lastRef表示上一次使用的相同的reference的tile

    这样的话PolyRef就拥有了和与删除之前同样的值

 

    从tile链表里面分配一个tile

   

}

Else

{

    通过decodePolyIdTile获得lastref的tile index

    也就是在m_tiles的下标

    dtMeshTile*target= &m_tiles[tileIndex];找到位置

    从m_nextFree开始顺着链表往下找,一直找到target为止

    Prev用来记录上一个找到哪个位置了,顺着链表找下来就是为了获得prev进而好删除

    if (!prev)说明刚上来就找到了,m_nextFree= tile->next;这样下次直接从m_nextFree开始分配就可以了,相当于把这个tile从freelist删除掉了

    else    prev->next= tile->next;也是删除掉了

 

    tile->salt= decodePolyIdSalt((dtPolyRef)lastRef);

    从ref里面获取salt

    注意salt是在removeTile的时候++的,所以在这里不用了

 

 

 

}

 

然后把这个tile插入到查找表里面

computeTileHash计算出hash值

然后

tile->next= m_posLookup[h];

    m_posLookup[h]= tile;

其实相当于把tile插在了m_posLookup[h]所指向的冲突链表的最前面

 

接下来从data里面获取数据把tile中的变量序列化

 

tile->bvTree是tile的包围盒的节点树

 

接下来构建tile->links

Links用来存储所有poly之间的连接关系,dtLink

 

然后初始化tile

给tile的一些数据赋值之后

connectIntLinks(tile);创建内部polygon的links

 

baseOffMeshLinks(tile);

就是把starting polygons和offmeshConnection相互连接起来

connectExtOffMeshLinks(tile,tile,-1);

把指向本tile的offmeshconnection与另一个tile(可以是同一个tile)上的所在poly连接起来

 

这两个步骤把offmeshconnection与start的poly和end的poly

都与offmeshconnection连接起来了

一个offmeshconnection相当于用了四个link

 

 

接下来创建neis

首先是跟同位置不同layer的tile连接

首先getTilesAt获得同一个xy的所有tile

执行下面四个函数:

connectExtLinks(tile,neis[j],-1);

让自己polyportal edgeneibour建立link

 

connectExtLinks(neis[j],tile,-1);

neibourpolyportaledge与自己建立link

 

connectExtOffMeshLinks(tile,neis[j],-1);

connectExtOffMeshLinks(neis[j],tile,-1);

把两个tile之间的offmeshconnection连接起来

 

然后是跟neibourTile连接

连接的方法是一样的

只不过获取neibourTile用的是

getNeighbourTilesAt(header->x,header->y,i,neis,MAX_NEIS);

也就是遍历身边的八个位置并且调用getTilesAt

 

====


dtNavMesh::connectIntLinks(dtMeshTile*tile)

对于tile里面的所有poly

如果是DT_POLYTYPE_OFFMESH_CONNECTION类型的过

通过判断每条边j的poly->neis[j]找到有连接别的多边形的边

分配tile->links中的一个link并赋值

并插入到poly->firstLink后面

这样的话我们就可以顺着poly->firstLink找到这个poly的所有的临接多边形

具体

对于tile中的所有dtPoly* poly

{

先让poly->firstLink= DT_NULL_LINK;

    poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION的过,不作处理

    for (intj= poly->vertCount-1;j>= 0; --j)

    {

    这里面是从poly的序号高的边到序号低的边

    在tile上分配一个link   allocLink

    并且给link赋值

link->ref = base | (dtPolyRef)(poly->neis[j]-1);//neibourpolyref值,base是本tilepoly ref base

        link->edge= (unsignedchar)j;//在本poly中的序号

        link->side= 0xff;//不是borderlink 的时候

    link->bmin= link->bmax= 0;//不是boarder link 的时候都是0

    然后把link插入到poly的firstLink

        link->next = poly->firstLink;

    poly->firstLink= idx;

    因为是在前面插入的

    所以poly的序号高的边到序号低的边循环的结果就是

    在firstlink当中的排列的序号是由低到高

}

}


====

dtNavMesh::baseOffMeshLinks(dtMeshTile*tile):建立内部offmeshConnection的链接

首先dtPolyRefbase= getPolyRefBase(tile);

getPolyRefBase会调用returnencodePolyId(tile->salt,it,0);

也就是最后的polygon的id会传0

所以就是获取了这个tile的polygonRef的base值

Polyref的三个组成部分:

@param[in]  salt    The tile's salt value.

@param[in]  it      The index of the tile.

@param[in]  ip      The index of the polygon within the tile.

对于tile中的所有offmeshconnection

从tile->polys里面获取其poly

constfloathalfExtents[3]= { con->rad,tile->header->walkableClimb,con->rad};

con->rad是存在InputGeom的floatm_offMeshConRads[MAX_OFFMESH_CONNECTIONS];里面的

是在addOffMeshConnection加的

值为m_agentRadius

是设定的:imguiSlider("Radius", &m_agentRadius,0.0f, 5.0f, 0.1f);

constfloat*p= &con->pos[0];offmeshconnection的第一个顶点

注意:

con->pos是从InputGeom的offMeshConVerts来的

赋值的时候:

float* v= &m_offMeshConVerts[m_offMeshConCount*3*2];

rcVcopy(&v[0],spos);

rcVcopy(&v[3],epos);

找到tile中p最近的polygon

dtPolyRef ref = findNearestPolyInTile(tile,p,halfExtents,nearestPt);

p 与 nearestPt的距离不能大于con->rad

float* v= &tile->verts[poly->verts[0]*3];

        dtVcopy(v, nearestPt);

如果p在一个polygon当中呢么这一步等于没用,但是如果不在,起码会让顶点在网格上面

然后allocLink在tile上分配一个link

link->ref= ref;

ref就是起始点所在的poly

插入到poly->firstLink

也就是让这个poly的link指向起始点所在poly

接下来让起始点所在的poly的link回指向off-mesh connection.

allocLink

通过ref找到起始点所在的landPoly

link->ref= base | (dtPolyRef)(con->poly);

插入到landPoly->firstLink


==

dtNavMesh::connectExtOffMeshLinks(dtMeshTile*tile,dtMeshTile*target,intside)

首先计算side的oppositeSide

对于所有target tile上的offmeshConnections

{

过滤掉targetCon->side!= oppositeSide的情况,因为我们只关注从target tile到本tile上的offmeshconnection

就要本tile上的offmeshconnection的oppositeSide与target tile上面的side一致

在本tile上进行connect的时候,side传入的是-1

    获得targetPoly= &target->polys[targetCon->poly];

    通过targettile上面的targetCon-poly获得targetPoly

    targetPoly->firstLink== DT_NULL_LINK表示targetPoly不可达,要忽略

   

    float* p= &targetCon->pos[3];

    pos[3]开始记录的是目标点,targetCon的目标点当然就是本tile上的endpoint

    ref = findNearestPolyInTile(tile,p,halfExtents,nearestPt);

    所以在本tile上获取poly

    然后就是真正连接的过程

    在target上allocLink(target);

    然后让link->ref = ref;指向当前tile上的那个poly

    插入到targetPoly->firstLink

    如果这个connection是DT_OFFMESH_CON_BIDIR

    也就是双向的connection

    那就要吧当前tile这个poly跟off-mesh connection 也link上

    所以:

    在tile上allocLink(tile);

    然后让link->ref = getPolyRefBase(target)| (dtPolyRef)(targetCon->poly);

    让这个link指向target tile上的targetCon的那个poly

    插入到landPoly->firstLink


}



====

dtNavMesh::connectExtLinks(dtMeshTile* tile,dtMeshTile* target, int side)

对于tile的每一个poly

对于poly的每一条边

过滤掉non-portal的边

获得临接边的两个顶点va vb

findConnectingPolys获取临接多边形

为每一个临接多边形分配一个link,(allocLink)

给link赋值

link->ref= nei[k];ref为这个link所指向的polygon

link->edge= (unsignedchar)j;属于哪条边

link->side= (unsignedchar)dir;

给link赋值并插入到poly->firstLink

float tmin = (neia[k*2+0]-va[2]) /(vb[2]-va[2]);

float tmax = (neia[k*2+1]-va[2]) /(vb[2]-va[2]);

是相对于这个poly的边va,vb来说,其临接多边形的临接边是从这个va,vb组成的边什么位置开始的,到什么位置结束,的一个比例。

也就是这条link所代表的neibour的边跨越了这个edge的从哪到哪的一部分

link->bmin= (unsignedchar)(dtClamp(tmin, 0.0f,1.0f)*255.0f);

link->bmax= (unsignedchar)(dtClamp(tmax, 0.0f,1.0f)*255.0f);

也就是吧tmin,tmax映射到0~255

poly->neis[j] & DT_EXT_LINK)表示是Tileborder

对于内部的link

因为// Normal connection

                                    

p->neis[j] = src[nvp+j]+1;


====

dtNavMesh::connectExtOffMeshLinks(dtMeshTile*tile,dtMeshTile*target,intside)

首先计算side的oppositeSide

对于所有target tile上的offmeshConnections

{

过滤掉targetCon->side!= oppositeSide的情况,因为我们只关注从target tile到本tile上的offmeshconnection

就要本tile上的offmeshconnection的oppositeSide与target tile上面的side一致

在本tile上进行connect的时候,side传入的是-1

    获得targetPoly= &target->polys[targetCon->poly];

    通过targettile上面的targetCon-poly获得targetPoly

    targetPoly->firstLink== DT_NULL_LINK表示targetPoly不可达,要忽略

   

    float* p= &targetCon->pos[3];

    pos[3]开始记录的是目标点,targetCon的目标点当然就是本tile上的endpoint

    ref = findNearestPolyInTile(tile,p,halfExtents,nearestPt);

    所以在本tile上获取poly

    然后就是真正连接的过程

    在target上allocLink(target);

    然后让link->ref = ref;指向当前tile上的那个poly

    插入到targetPoly->firstLink

    如果这个connection是DT_OFFMESH_CON_BIDIR

    也就是双向的connection

    那就要吧当前tile这个poly跟off-mesh connection 也link上

    所以:

    在tile上allocLink(tile);

    然后让link->ref = getPolyRefBase(target)| (dtPolyRef)(targetCon->poly);

    让这个link指向target tile上的targetCon的那个poly

    插入到landPoly->firstLink

}






猜你喜欢

转载自blog.csdn.net/icebergliu1234/article/details/80322392