以下为个人学习笔记整理,源项目 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」的 smaxy = rcClamp(span.smax, 0, 0xffff);
  • reg:记录「CompactSpan」所属区域编号
  • con:周围(前后左右)四个方向上「CompactSpan」连通数据,每 6 bit 标识一个方向
    • 每个方向记录的是相邻位置的第几个「CompactSpan」和自己连通,因此可以用相邻位置的 idx + con[dir] 来获取到相邻「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」。

因此可用首个「CompactSpanidx + 该列的「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

Region」的「Contour」 数据。

  • 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

多边形边信息,一条边最多被两个多边形共用

image-20211104170603387

  • 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.npolys

  • nverts:「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;
};

# 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.
};
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.
}
  • 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.
};

# PolyMesh 相关数据

# PolyMeshDetail 相关数据

# 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; }
};
/// 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
更新于 阅读次数

请我[恰饭]~( ̄▽ ̄)~*

鑫酱(●'◡'●) 微信支付

微信支付

鑫酱(●'◡'●) 支付宝

支付宝