以下为个人学习笔记整理,源项目 github 链接。
# Recast Navigation 源码阅读
# 基础属性
# CellSize
单个「Span」的长宽
# CellHeight
单个「Span」的最小高度
# AgentHeight
行走对象的高度
# AgentRadius
行走对象的步长半径
# AgentMaxClimb
行走对象的最大爬坡高度
# MaxEdgeError
面片和几何物体的距离,可以理解为面片和几何的贴合程度,越小贴合越紧密,面片越多
# VertsPerPoly
多边形的最大顶点数
# Recast 基础数据结构
# Span
体素化的最小单位,用于表示固定长宽(CellSize),可变高的矩形区域。
- smin:矩形区域的最低点的 y 坐标
 - smax:矩形区域的最高点的 y 坐标
 - area:可行走状态,标识该「Span」上表面能否行走(0:不能,64:可以)
 - next:指向同 x-z 坐标的下一个「Span」
 
/// Represents a span in a heightfield. | |
/// @see rcHeightfield | |
struct rcSpan  | |
{ | |
unsigned int smin : RC_SPAN_HEIGHT_BITS; ///< The lower limit of the span. [Limit: < #smax]  | |
unsigned int smax : RC_SPAN_HEIGHT_BITS; ///< The upper limit of the span. [Limit: <= #RC_SPAN_MAX_HEIGHT]  | |
unsigned int area : 6; ///< The area id assigned to the span.  | |
rcSpan* next; ///< The next span higher up in column.  | |
};  | 
# SpanPool
对于「Span」的内存池。
- RC_SPANS_PER_POOL:默认 2048 个
 - next:指向下一个「SpanPool」
 
/// A memory pool used for quick allocation of spans within a heightfield. | |
/// @see rcHeightfield | |
struct rcSpanPool  | |
{ | |
rcSpanPool* next; ///< The next span pool.  | |
rcSpan items[RC_SPANS_PER_POOL]; ///< Array of spans in the pool.  | |
};  | 
# Heightfield
用来表示模型的高度场,管理场景中的三角形面片所产生的「Span」。
- width:max_x / CellSize
 - height:max_y / CellHeight
 - bmin:(min_x, min_y, min_z),用于表示场景包围盒的左下边界
 - bmax:(max_x, max_y,max_z),用于表示场景包围盒的右上边界
 - cs:CellSize
 - ch:CellHeight
 - spans:「Span」的指针数组,记录 x-z 平面上(width * height 个)「Span」的首对象
 - pools:「SpanPool」链表的链头,用于申请内存创建「Span」
 - freelist:管理「SpanPool」创建出并且空闲未被使用的「Span」
 
/// A dynamic heightfield representing obstructed space. | |
/// @ingroup recast | |
struct rcHeightfield  | |
{ | |
rcHeightfield();  | |
~rcHeightfield();  | |
int width; ///< The width of the heightfield. (Along the x-axis in cell units.)  | |
int height; ///< The height of the heightfield. (Along the z-axis in cell units.)  | |
float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)]  | |
float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)]  | |
float cs; ///< The size of each cell. (On the xz-plane.)  | |
float ch; ///< The height of each cell. (The minimum increment along the y-axis.)  | |
rcSpan** spans; ///< Heightfield of spans (width*height).  | |
rcSpanPool* pools; ///< Linked list of span pools.  | |
rcSpan* freelist; ///< The next free span.  | |
private:  | |
	// Explicitly-disabled copy constructor and copy assignment operator. | |
rcHeightfield(const rcHeightfield&);  | |
rcHeightfield& operator=(const rcHeightfield&);  | |
};  | 
# CompactSpan
记录可行走「Span」的上表面高度等信息。
- y:可行走「Span」的 
smax值y = rcClamp(span.smax, 0, 0xffff); - reg:记录「CompactSpan」所属区域编号
 - con:周围(前后左右)四个方向上「CompactSpan」连通数据,每 
6bit 标识一个方向- 每个方向记录的是相邻位置的第几个「CompactSpan」和自己连通,因此可以用相邻位置的 
idx + con[dir]来获取到相邻「CompactSpan」 
 - 每个方向记录的是相邻位置的第几个「CompactSpan」和自己连通,因此可以用相邻位置的 
 - h:y 坐标和下一个「Span」的 
smmin的差h = rcClamp(y - span->next->smin, 0, 0xffff); 
/// Represents a span of unobstructed space within a compact heightfield. | |
struct rcCompactSpan  | |
{ | |
unsigned short y; ///< The lower extent of the span. (Measured from the heightfield's base.)  | |
unsigned short reg; ///< The id of the region the span belongs to. (Or zero if not in a region.)  | |
unsigned int con : 24; ///< Packed neighbor connection data.  | |
unsigned int h : 8; ///< The height of the span. (Measured from #y.)  | |
};  | 
# CompactCell
通过第一个编号和个数,可以快速遍历所有「CompactSpan」。
- index:该「CompactCell」列从下往上第一个「CompactSpan」的 
idx- 「CompactSpan」编号在 y 轴方向是递增的
 
 - count:每个「CompactCell」包含的「CompactSpan」个数
 
因此可用首个「CompactSpan」
idx+ 该列的「CompactSpan」个数count来遍历整列的「CompactSpan」
/// Provides information on the content of a cell column in a compact heightfield.  | |
struct rcCompactCell  | |
{ | |
unsigned int index : 24; ///< Index to the first span in the column.  | |
unsigned int count : 8; ///< Number of spans in the column.  | |
};  | 
# CompactHeightfield
用来表示不存在遮挡的空间。
- width:max_x / CellSize
 - height:max_y / CellHeight
 - spanCount:「CompactSpan」数量。
 - walkableHeight:AgentHeight,上下两个「CompactSpan」太近的情况下会影响能否站立
 - walkableClimb:AgentMaxClimb,「CompactSpan」内三角形片面倾斜程度会影响能否站立
 - borderSize:边界大小。「Region」的外轮廓大小。
 - maxDistance:构建「高度场」的「距离场」时,缓存的最大距离,用于分水岭算法的起始漫灌高度
 - maxRegions:临时记录「Region」的数量,用于「Region」合并和再编排
 - bmin:(min_x, min_y, min_z),用于表示场景包围盒的左下边界
 - bmax:(max_x, max_y,max_z),用于表示场景包围盒的右上边界
 - cs:CellSize
 - ch:CellHeight
 - cells:「CompactCell」数组
 - spans:「CompactSpan」数组
 - dist:临时记录每个「CompactSpan」的「场距」,用于划分「Region」
 - areas:记录每个「CompactSpan」的可行走状态
 
/// A compact, static heightfield representing unobstructed space. | |
/// @ingroup recast | |
struct rcCompactHeightfield  | |
{ | |
rcCompactHeightfield();  | |
~rcCompactHeightfield();  | |
int width; ///< The width of the heightfield. (Along the x-axis in cell units.)  | |
int height; ///< The height of the heightfield. (Along the z-axis in cell units.)  | |
int spanCount; ///< The number of spans in the heightfield.  | |
int walkableHeight; ///< The walkable height used during the build of the field. (See: rcConfig::walkableHeight)  | |
int walkableClimb; ///< The walkable climb used during the build of the field. (See: rcConfig::walkableClimb)  | |
int borderSize; ///< The AABB border size used during the build of the field. (See: rcConfig::borderSize)  | |
unsigned short maxDistance; ///< The maximum distance value of any span within the field.  | |
unsigned short maxRegions; ///< The maximum region id of any span within the field.  | |
float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)]  | |
float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)]  | |
float cs; ///< The size of each cell. (On the xz-plane.)  | |
float ch; ///< The height of each cell. (The minimum increment along the y-axis.)  | |
rcCompactCell* cells; ///< Array of cells. [Size: #width*#height]  | |
rcCompactSpan* spans; ///< Array of spans. [Size: #spanCount]  | |
unsigned short* dist; ///< Array containing border distance data. [Size: #spanCount]  | |
unsigned char* areas; ///< Array containing area id data. [Size: #spanCount]  | |
};  | 
# Regions 相关数据结构
# Region
多个「CompactSpan」组成的区域。
- spanCount:「CompactSpan」数量
 - id: 
region_id - areaType:记录「Region」的可行走状态,继承于 
CompactHeightfield.areas - remap:是否重新编排
 - visited:是否已经访问过
 - overlap:是否有重叠
 - ymin:「Region」内所有「CompactSpan」的最小 
y - ymax:「Region」内所有「CompactSpan」的最大 
y - connectsToBorder:是否和轮廓(BorderSize)相邻
 - connections:记录该「Region」能连通的其他「Region」的 
region_id - floors:记录和该「Region」的重叠的「Region」的 
region_id 
struct rcRegion  | |
{ | |
inline rcRegion(unsigned short i) :  | |
spanCount(0),  | |
id(i),  | |
areaType(0),  | |
remap(false),  | |
visited(false),  | |
overlap(false),  | |
connectsToBorder(false),  | |
ymin(0xffff),  | |
ymax(0)  | |
{}  | |
int spanCount; // Number of spans belonging to this region  | |
unsigned short id; // ID of the region  | |
unsigned char areaType; // Are type.  | |
bool remap;  | |
bool visited;  | |
bool overlap;  | |
bool connectsToBorder; // neighbor is border  | |
unsigned short ymin, ymax;  | |
	rcIntArray connections; | |
	rcIntArray floors; | |
} | 
# Contour
用于记录单个「Region」轮廓顶点数据。
- nverts:「simplify」后的「Region」轮廓顶点数量
 - verts:「simplify」后的「Region」轮廓顶点数据 
[x, y, z, neighbor_region_id] * nverts - nrverts:「simplify」前的「Region」轮廓顶点数量
 - rverts:「simplify」前的「Region」轮廓顶点数据 
[x, y, z, neighbor_region_id] * nverts - reg:轮廓顶点所表示的「Region」的 
region_id - area:轮廓顶点所表示的「Region」的 
area_type地形类型 
struct rcContour  | |
{ | |
int* verts; ///< Simplified contour vertex and connection data. [Size: 4 * #nverts]  | |
int nverts; ///< The number of vertices in the simplified contour.  | |
int* rverts; ///< Raw contour vertex and connection data. [Size: 4 * #nrverts]  | |
int nrverts; ///< The number of vertices in the raw contour.  | |
unsigned short reg; ///< The region id of the contour.  | |
unsigned char area; ///< The area id of the contour.  | |
};  | 
# ContourSet
「Contour」集合管理器,存储所有「Region」的轮廓顶点数据。
- conts:「Contour」数组,记录所有「Region」的轮廓顶点数据
 - nconts: 
len(conts) - bmin:(min_x, min_y, min_z),用于表示场景包围盒的左下边界
 - bmax:(max_x, max_y,max_z),用于表示场景包围盒的右上边界
 - cs:CellSize
 - ch:CellHeight
 - width:max_x / CellSize
 - height:max_y / CellHeight
 - borderSize:边界大小,「Region」的外轮廓
 - maxError:MaxEdgeError
 
struct rcContourSet  | |
{ | |
rcContourSet();  | |
~rcContourSet();  | |
rcContour* conts; ///< An array of the contours in the set. [Size: #nconts]  | |
int nconts; ///< The number of contours in the set.  | |
float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)]  | |
float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)]  | |
float cs; ///< The size of each cell. (On the xz-plane.)  | |
float ch; ///< The height of each cell. (The minimum increment along the y-axis.)  | |
int width; ///< The width of the set. (Along the x-axis in cell units.)  | |
int height; ///< The height of the set. (Along the z-axis in cell units.)  | |
int borderSize; ///< The AABB border size used to generate the source data from which the contours were derived.  | |
float maxError; ///< The MaxEdgeError that this contour set was simplified with.  | |
};  | 
# ContourHole
- contour:记录对应 
region_id的「Contour」 数据,只记录凹多边形 - minx, minz, leftmost:凹多边形的左下角顶点坐标和顶点编号
 
struct rcContourHole  | |
{ | |
rcContour* contour;  | |
int minx, minz, leftmost;  | |
};  | 
# ContourRegion
- outline:记录对应 
region_id的「Contour」 数据,只记录凸多边形 - nholes:记录对应 
region_id的凹多边形轮廓数量,理论上应该只有一个 - holes:凹多边形数值的起始索引,配合 
nholes可以获取所有的凹多边形 
struct rcContourRegion  | |
{ | |
rcContour* outline;  | |
rcContourHole* holes;  | |
int nholes;  | |
};  | 
# PotentialDiagonal
- vert:顶点在「Contour」的下标
 - dist:该凸多边形顶点和某个凹多边形顶点的距离平方
 
struct rcPotentialDiagonal  | |
{ | |
int vert;  | |
int dist;  | |
};  | 
# Mesh 相关数据结构
# Edge
多边形边信息,一条边最多被两个多边形共用

- vert:首尾顶点编号
 - poly:该条边所属的多边形编号,由于可能有两个多边形共用,所以 0 记录升序的多边形,1 记录降序的多边形
 - polyEdge:多边形内的边编号,由于可能有两个多边形共用,所以 0 记录升序边编号,1 记录降序边编号
 
struct rcEdge  | |
{ | |
unsigned short vert[2];  | |
unsigned short polyEdge[2];  | |
unsigned short poly[2];  | |
};  | 
# PolyMesh
记录所有「Poly」数据
- verts:全部「Region」轮廓的所有顶点集合
 - polys:2 倍的 
npolys大小,|_0_|_1_| * npolys- 前半部分记录每个多边形各个顶点的顶点编号 
|_0_| - 后半部分记录每条边相邻的多边形编号 
|_1_| 
 - 前半部分记录每个多边形各个顶点的顶点编号 
 - regs:记录每个「Poly」的 
region_id - flags:标记地形类型,值取决于 
areas 
enum SamplePolyFlags  | |
{ | |
SAMPLE_POLYFLAGS_WALK = 0x01, // Ability to walk (ground, grass, road)  | |
SAMPLE_POLYFLAGS_SWIM = 0x02, // Ability to swim (water).  | |
SAMPLE_POLYFLAGS_DOOR = 0x04, // Ability to move through doors.  | |
SAMPLE_POLYFLAGS_JUMP = 0x08, // Ability to jump.  | |
SAMPLE_POLYFLAGS_DISABLED = 0x10, // Disabled polygon  | |
SAMPLE_POLYFLAGS_ALL = 0xffff // All abilities.  | |
};  | 
- areas:记录每个「Poly」的 
area_type地形类型 - nverts:去重之后的「Contour」顶点数量
 - npolys:合并后的多边形数量
 - maxpolys:最大「Poly」数量
 - nvp:VertsPerPoly
 - bmin:(min_x, min_y, min_z),用于表示场景包围盒的左下边界
 - bmax:(max_x, max_y,max_z),用于表示场景包围盒的右上边界
 - cs:CellSize
 - ch:CellHeight
 - borderSize:边界大小,「Region」的外轮廓
 - maxError:MaxEdgeError
 
struct rcPolyMesh  | |
{ | |
rcPolyMesh();  | |
~rcPolyMesh();  | |
unsigned short* verts; ///< The mesh vertices. [Form: (x, y, z) * #nverts]  | |
unsigned short* polys; ///< Polygon and neighbor data. [Length: #maxpolys * 2 * #nvp]  | |
unsigned short* regs; ///< The region id assigned to each polygon. [Length: #maxpolys]  | |
unsigned short* flags; ///< The user defined flags for each polygon. [Length: #maxpolys]  | |
unsigned char* areas; ///< The area id assigned to each polygon. [Length: #maxpolys]  | |
int nverts; ///< The number of vertices.  | |
int npolys; ///< The number of polygons.  | |
int maxpolys; ///< The number of allocated polygons.  | |
int nvp; ///< The maximum number of vertices per polygon.  | |
float bmin[3]; ///< The minimum bounds in world space. [(x, y, z)]  | |
float bmax[3]; ///< The maximum bounds in world space. [(x, y, z)]  | |
float cs; ///< The size of each cell. (On the xz-plane.)  | |
float ch; ///< The height of each cell. (The minimum increment along the y-axis.)  | |
int borderSize; ///< The AABB border size used to generate the source data from which the mesh was derived.  | |
float maxEdgeError; ///< The max error of the polygon edges in the mesh.  | |
};  | 
# PolyMeshDetail
以每个「Poly」为单位,记录「Poly」经过采样和切分后得到的三角形信息
meshes:四个元素的数组,每四个元素表示一个「Poly」的数据信息,四个元素代表含义如下
- 多边形首个顶点的顶点编号
 - 总顶点数量,包括内部新增的
 - 多边形首个三角形的编号
 - 总三角形数量
 
verts:记录所有「Poly」经过采样和切分后的顶点
tris:记录所有「Poly」经过采样和切分后的三角形
nmeshes:「Poly」数量,同
PolyMesh.npolysnverts:「Poly」的总顶点数量
len(verts)ntris:「Poly」的总三角形数量
len(tris)
/// Contains triangle meshes that represent detailed height data associated  | |
/// with the polygons in its associated polygon mesh object. | |
/// @ingroup recast | |
struct rcPolyMeshDetail  | |
{ | |
unsigned int* meshes; ///< The sub-mesh data. [Size: 4*#nmeshes]  | |
float* verts; ///< The mesh vertices. [Size: 3*#nverts]  | |
unsigned char* tris; ///< The mesh triangles. [Size: 4*#ntris]  | |
int nmeshes; ///< The number of sub-meshes defined by #meshes.  | |
int nverts; ///< The number of vertices in #verts.  | |
int ntris; ///< The number of triangles in #tris.  | |
};  | 
# HeightPatch
记录单个「Poly」的高度相关数据
- data:记录「Poly」AABB 包围盒内每个同 
region_id点所代表的「CompactSpan」的上表面高度 - xmin:「Poly」所有顶点的最小 
x坐标 - ymin:「Poly」所有顶点的最小 
z坐标 - with:「Poly」最大最小顶点的 
x轴跨度 (包围盒长) - height:「Poly」最大最小顶点的 
z轴跨度 (包围盒宽) 
struct rcHeightPatch  | |
{ | |
inline rcHeightPatch() : data(0), xmin(0), ymin(0), width(0), height(0) {}  | |
inline ~rcHeightPatch() { rcFree(data); }  | |
unsigned short* data; // all poly xz-plane AABB maxhw,maxhh  | |
int xmin, ymin, width, height;  | |
};  | 
# NavMesh 相关数据结构
# MeshTile
/// Defines a navigation mesh tile. | |
/// @ingroup detour | |
struct dtMeshTile  | |
{ | |
unsigned int salt; ///< Counter describing modifications to the tile.  | |
unsigned int linksFreeList; ///< Index to the next free link.  | |
dtMeshHeader* header; ///< The tile header.  | |
dtPoly* polys; ///< The tile polygons. [Size: dtMeshHeader::polyCount]  | |
float* verts; ///< The tile vertices. [Size: dtMeshHeader::vertCount]  | |
dtLink* links; ///< The tile links. [Size: dtMeshHeader::maxLinkCount]  | |
dtPolyDetail* detailMeshes; ///< The tile's detail sub-meshes. [Size: dtMeshHeader::detailMeshCount]  | |
	/// The detail mesh's unique vertices. [(x, y, z) * dtMeshHeader::detailVertCount] | |
float* detailVerts;  | |
	/// The detail mesh's triangles. [(vertA, vertB, vertC, triFlags) * dtMeshHeader::detailTriCount]. | |
	/// See dtDetailTriEdgeFlags and dtGetDetailTriEdgeFlags. | |
unsigned char* detailTris;  | |
	/// The tile bounding volume nodes. [Size: dtMeshHeader::bvNodeCount] | |
	/// (Will be null if bounding volumes are disabled.) | |
dtBVNode* bvTree;  | |
dtOffMeshConnection* offMeshCons; ///< The tile off-mesh connections. [Size: dtMeshHeader::offMeshConCount]  | |
unsigned char* data; ///< The tile data. (Not directly accessed under normal situations.)  | |
int dataSize; ///< Size of the tile data.  | |
int flags; ///< Tile flags. (See: #dtTileFlags)  | |
dtMeshTile* next; ///< The next free tile, or the next tile in the spatial grid.  | |
};  | 
# NavMesh
class dtNavMesh  | |
{ | |
public:  | |
    //... | |
private:  | |
dtNavMeshParams m_params; ///< Current initialization params. TODO: do not store this info twice.  | |
float m_orig[3]; ///< Origin of the tile (0,0)  | |
float m_tileWidth, m_tileHeight; ///< Dimensions of each tile.  | |
int m_maxTiles; ///< Max number of tiles.  | |
int m_tileLutSize; ///< Tile hash lookup size (must be pot).  | |
int m_tileLutMask; ///< Tile hash lookup mask.  | |
dtMeshTile** m_posLookup; ///< Tile hash lookup.  | |
dtMeshTile* m_nextFree; ///< Freelist of tiles.  | |
dtMeshTile* m_tiles; ///< List of tiles.  | |
} | 
# NavMeshParams
- orig[3]: 
bmin - tileWidth: 
max_x - min_x - tileHeight: 
max_z - min_z - maxPolys:「PolyMesh」的 
npolys 
/// Configuration parameters used to define multi-tile navigation meshes. | |
/// The values are used to allocate space during the initialization of a navigation mesh. | |
/// @see dtNavMesh::init() | |
/// @ingroup detour | |
struct dtNavMeshParams  | |
{ | |
float orig[3]; ///< The world space origin of the navigation mesh's tile space. [(x, y, z)]  | |
float tileWidth; ///< The width of each tile. (Along the x-axis.)  | |
float tileHeight; ///< The height of each tile. (Along the z-axis.)  | |
int maxTiles; ///< The maximum number of tiles the navigation mesh can contain. This and maxPolys are used to calculate how many bits are needed to identify tiles and polygons uniquely.  | |
int maxPolys; ///< The maximum number of polygons each tile can contain. This and maxTiles are used to calculate how many bits are needed to identify tiles and polygons uniquely.  | |
};  | 
# NavMeshCreateParams
# PolyMesh 相关数据
- verts:「PolyMesh」的 
verts - vertCount:「PolyMesh」的 
nverts - polys:「PolyMesh」的 
polys - polyAreas:「PolyMesh」的 
areas - polyFlags:「PolyMesh」的 
flags - polyCount:「PolyMesh」的 
npolys - nvp:「PolyMesh」的 
nvp 
# PolyMeshDetail 相关数据
- detailMeshes:「PolyMeshDetail」的 
meshes - detailVerts:「PolyMeshDetail」的 
verts - detailVertsCount:「PolyMeshDetail」的 
nverts - detailTris:「PolyMeshDetail」的 
tris - detailTriCount:「PolyMeshDetail」的 
ntris 
# OffMeshConnection 相关数据
自定义的一些导航链接数据
- offMeshConVerts:
 - offMeshConRad:
 - offMeshConDir:
 - offMeshConAreas:
 - offMeshConFlags:
 - offMeshConUserID:
 - offMeshConCount:
 
# Tile 相关数据
- userId:
 - tileX:
 - tileY:
 - tileLayer:
 
# General Configuration 相关数据
- walkableHeight:AgentHeight
 - walkableRadius:AgentRadius
 - walkableClimb:AgentMaxClimb
 - bmin:(min_x, min_y, min_z),用于表示场景包围盒的左下边界
 - bmax:(max_x, max_y,max_z),用于表示场景包围盒的右上边界
 - cs:CellSize
 - ch:CellHeight
 - buildBvTree:标记是否需要构建 BVTree
 
struct dtNavMeshCreateParams  | |
{ | |
	/// @name Polygon Mesh Attributes | |
	/// Used to create the base navigation graph. | |
	/// See #rcPolyMesh for details related to these attributes. | |
	/// @{ | |
const unsigned short* verts; ///< The polygon mesh vertices. [(x, y, z) * #vertCount] [Unit: vx]  | |
int vertCount; ///< The number vertices in the polygon mesh. [Limit: >= 3]  | |
const unsigned short* polys; ///< The polygon data. [Size: #polyCount * 2 * #nvp]  | |
const unsigned short* polyFlags; ///< The user defined flags assigned to each polygon. [Size: #polyCount]  | |
const unsigned char* polyAreas; ///< The user defined area ids assigned to each polygon. [Size: #polyCount]  | |
int polyCount; ///< Number of polygons in the mesh. [Limit: >= 1]  | |
int nvp; ///< Number maximum number of vertices per polygon. [Limit: >= 3]  | |
	/// @} | |
	/// @name Height Detail Attributes (Optional) | |
	/// See #rcPolyMeshDetail for details related to these attributes. | |
	/// @{ | |
const unsigned int* detailMeshes; ///< The height detail sub-mesh data. [Size: 4 * #polyCount]  | |
const float* detailVerts; ///< The detail mesh vertices. [Size: 3 * #detailVertsCount] [Unit: wu]  | |
int detailVertsCount; ///< The number of vertices in the detail mesh.  | |
const unsigned char* detailTris; ///< The detail mesh triangles. [Size: 4 * #detailTriCount]  | |
int detailTriCount; ///< The number of triangles in the detail mesh.  | |
	/// @} | |
	/// @name Off-Mesh Connections Attributes (Optional) | |
	/// Used to define a custom point-to-point edge within the navigation graph, an  | |
	/// off-mesh connection is a user defined traversable connection made up to two vertices,  | |
	/// at least one of which resides within a navigation mesh polygon. | |
	/// @{ | |
	/// Off-mesh connection vertices. [(ax, ay, az, bx, by, bz) * #offMeshConCount] [Unit: wu] | |
const float* offMeshConVerts;  | |
	/// Off-mesh connection radii. [Size: #offMeshConCount] [Unit: wu] | |
const float* offMeshConRad;  | |
	/// User defined flags assigned to the off-mesh connections. [Size: #offMeshConCount] | |
const unsigned short* offMeshConFlags;  | |
	/// User defined area ids assigned to the off-mesh connections. [Size: #offMeshConCount] | |
const unsigned char* offMeshConAreas;  | |
	/// The permitted travel direction of the off-mesh connections. [Size: #offMeshConCount] | |
	/// | |
	/// 0 = Travel only from endpoint A to endpoint B.<br/> | |
	/// #DT_OFFMESH_CON_BIDIR = Bidirectional travel. | |
const unsigned char* offMeshConDir;  | |
	/// The user defined ids of the off-mesh connection. [Size: #offMeshConCount] | |
const unsigned int* offMeshConUserID;  | |
	/// The number of off-mesh connections. [Limit: >= 0] | |
int offMeshConCount;  | |
	/// @} | |
	/// @name Tile Attributes | |
	/// @note The tile grid/layer data can be left at zero if the destination is a single tile mesh. | |
	/// @{ | |
unsigned int userId; ///< The user defined id of the tile.  | |
int tileX; ///< The tile's x-grid location within the multi-tile destination mesh. (Along the x-axis.)  | |
int tileY; ///< The tile's y-grid location within the multi-tile desitation mesh. (Along the z-axis.)  | |
int tileLayer; ///< The tile's layer within the layered destination mesh. [Limit: >= 0] (Along the y-axis.)  | |
float bmin[3]; ///< The minimum bounds of the tile. [(x, y, z)] [Unit: wu]  | |
float bmax[3]; ///< The maximum bounds of the tile. [(x, y, z)] [Unit: wu]  | |
	/// @} | |
	/// @name General Configuration Attributes | |
	/// @{ | |
float walkableHeight; ///< The agent height. [Unit: wu]  | |
float walkableRadius; ///< The agent radius. [Unit: wu]  | |
float walkableClimb; ///< The agent maximum traversable ledge. (Up/Down) [Unit: wu]  | |
float cs; ///< The xz-plane cell size of the polygon mesh. [Limit: > 0] [Unit: wu]  | |
float ch; ///< The y-axis cell height of the polygon mesh. [Limit: > 0] [Unit: wu]  | |
	/// True if a bounding volume tree should be built for the tile. | |
	/// @note The BVTree is not normally needed for layered navigation meshes. | |
bool buildBvTree;  | |
	/// @} | |
};  | 
# MeshHeader
- bvNodeCount: 
buildBvTree ? polyCount*2 : 0; - bvQuantFactor: 
1.0f / cs; 
/// Provides high level information related to a dtMeshTile object. | |
/// @ingroup detour | |
struct dtMeshHeader  | |
{ | |
int magic; ///< Tile magic number. (Used to identify the data format.)  | |
int version; ///< Tile data format version number.  | |
int x; ///< The x-position of the tile within the dtNavMesh tile grid. (x, y, layer)  | |
int y; ///< The y-position of the tile within the dtNavMesh tile grid. (x, y, layer)  | |
int layer; ///< The layer of the tile within the dtNavMesh tile grid. (x, y, layer)  | |
unsigned int userId; ///< The user defined id of the tile.  | |
int polyCount; ///< The number of polygons in the tile.  | |
int vertCount; ///< The number of vertices in the tile.  | |
int maxLinkCount; ///< The number of allocated links.  | |
int detailMeshCount; ///< The number of sub-meshes in the detail mesh.  | |
	/// The number of unique vertices in the detail mesh. (In addition to the polygon vertices.) | |
int detailVertCount;  | |
int detailTriCount; ///< The number of triangles in the detail mesh.  | |
int bvNodeCount; ///< The number of bounding volume nodes. (Zero if bounding volumes are disabled.)  | |
int offMeshConCount; ///< The number of off-mesh connections.  | |
int offMeshBase; ///< The index of the first polygon which is an off-mesh connection.  | |
float walkableHeight; ///< The height of the agents using the tile.  | |
float walkableRadius; ///< The radius of the agents using the tile.  | |
float walkableClimb; ///< The maximum climb height of the agents using the tile.  | |
float bmin[3]; ///< The minimum bounds of the tile's AABB. [(x, y, z)]  | |
float bmax[3]; ///< The maximum bounds of the tile's AABB. [(x, y, z)]  | |
	/// The bounding volume quantization factor.  | |
float bvQuantFactor;  | |
};  | 
# Poly
/// Defines a polygon within a dtMeshTile object. | |
/// @ingroup detour | |
struct dtPoly  | |
{ | |
	/// Index to first link in linked list. (Or #DT_NULL_LINK if there is no link.) | |
unsigned int firstLink;  | |
	/// The indices of the polygon's vertices. | |
	/// The actual vertices are located in dtMeshTile::verts. | |
unsigned short verts[DT_VERTS_PER_POLYGON];  | |
	/// Packed data representing neighbor polygons references and flags for each edge. | |
unsigned short neis[DT_VERTS_PER_POLYGON];  | |
	/// The user defined polygon flags. | |
unsigned short flags;  | |
	/// The number of vertices in the polygon. | |
unsigned char vertCount;  | |
	/// The bit packed area id and polygon type. | |
	/// @note Use the structure's set and get methods to acess this value. | |
unsigned char areaAndtype;  | |
	/// Sets the user defined area id. [Limit: < #DT_MAX_AREAS] | |
inline void setArea(unsigned char a) { areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f); }  | |
	/// Sets the polygon type. (See: #dtPolyTypes.) | |
inline void setType(unsigned char t) { areaAndtype = (areaAndtype & 0x3f) | (t << 6); }  | |
	/// Gets the user defined area id. | |
inline unsigned char getArea() const { return areaAndtype & 0x3f; }  | |
	/// Gets the polygon type. (See: #dtPolyTypes) | |
inline unsigned char getType() const { return areaAndtype >> 6; }  | |
};  | 
# Link
/// Defines a link between polygons. | |
/// @note This structure is rarely if ever used by the end user. | |
/// @see dtMeshTile | |
struct dtLink  | |
{ | |
dtPolyRef ref; ///< Neighbour reference. (The neighbor that is linked to.)  | |
unsigned int next; ///< Index of the next link.  | |
unsigned char edge; ///< Index of the polygon edge that owns this link.  | |
unsigned char side; ///< If a boundary link, defines on which side the link is.  | |
unsigned char bmin; ///< If a boundary link, defines the minimum sub-edge area.  | |
unsigned char bmax; ///< If a boundary link, defines the maximum sub-edge area.  | |
};  | 
# PolyDetail
/// Defines the location of detail sub-mesh data within a dtMeshTile. | |
struct dtPolyDetail  | |
{ | |
unsigned int vertBase; ///< The offset of the vertices in the dtMeshTile::detailVerts array.  | |
unsigned int triBase; ///< The offset of the triangles in the dtMeshTile::detailTris array.  | |
unsigned char vertCount; ///< The number of vertices in the sub-mesh.  | |
unsigned char triCount; ///< The number of triangles in the sub-mesh.  | |
};  | 
# BVNode
- i:node 编号,正数表示叶节点在数组的下标;负数表示根节点,数值表示根节点下所有节点数量
 
/// Bounding volume node. | |
/// @note This structure is rarely if ever used by the end user. | |
/// @see dtMeshTile | |
struct dtBVNode  | |
{ | |
unsigned short bmin[3]; ///< Minimum bounds of the node's AABB. [(x, y, z)]  | |
unsigned short bmax[3]; ///< Maximum bounds of the node's AABB. [(x, y, z)]  | |
int i; ///< The node's index. (Negative for escape sequence.)  | |
};  | 
# OffMeshConnection 相关数据
# OffMeshConnection
/// Defines an navigation mesh off-mesh connection within a dtMeshTile object. | |
/// An off-mesh connection is a user defined traversable connection made up to two vertices. | |
struct dtOffMeshConnection  | |
{ | |
	/// The endpoints of the connection. [(ax, ay, az, bx, by, bz)] | |
float pos[6];  | |
	/// The radius of the endpoints. [Limit: >= 0] | |
float rad;  | |
	/// The polygon reference of the connection within the tile. | |
unsigned short poly;  | |
	/// Link flags.  | |
	/// @note These are not the connection's user defined flags. Those are assigned via the  | |
	/// connection's dtPoly definition. These are link flags used for internal purposes. | |
unsigned char flags;  | |
	/// End point side. | |
unsigned char side;  | |
	/// The id of the offmesh connection. (User assigned when the navigation mesh is built.) | |
unsigned int userId;  | |
};  | 
# 细节说明
# neighbor connection data
用于记录相邻的前后左右「Span」连通情况,单个方向只会记录第一个满足相邻条件的「Span」
由 24 bit 构成,6bit 表示一个方位。如果不连通则值为 0x3f
/// Gets neighbor connection data for the specified direction. | |
///  @param[in]		s		The span to check. | |
///  @param[in]		dir		The direction to check. [Limits: 0 <= value < 4] | |
///  @return The neighbor connection data for the specified direction, | |
///  	or #RC_NOT_CONNECTED if there is no connection. | |
/// RC_NOT_CONNECTED == 0X3F | |
inline int rcGetCon(const rcCompactSpan& s, int dir)  | |
{ | |
const unsigned int shift = (unsigned int)dir*6;  | |
return (s.con >> shift) & 0x3f;  | |
} | 
dir 方向说明:
///dir: 0~4 左前右后 | |
/// 0:x-1 | |
/// 1:z+1 | |
/// 2:x+1 | |
/// 3:z-1 | |
offset[4] = { -1, 1, 1, -1 };  | 
# 参考资料
- 传送门大汇总:https://www.jianshu.com/p/64469a410b5d
 - unity Navigation:https://docs.unity3d.com/Manual/Navigation.html
 - gen navmash:http://critterai.org/
 - 基础篇:https://www.jianshu.com/p/c0d209630c6b