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);
让自己poly的portal edge与neibour建立link
connectExtLinks(neis[j],tile,-1);
让neibourpoly的portaledge与自己建立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);//neibourpoly的ref值,base是本tile的poly 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
}