工具软件
Excel
Nodepad++
Sublime
Unity 5.4 / 5.6
VS
RecastDemo
CodeBlocks
分析过程以Unity项目-Demo13为例
一. 创建测试模型
在Unity里搭建一个简单的寻路模型,并导出模型obj到Recastnavigation.
首先, 寻路模型要尽可能简单,(在Unity里,只包含2个NavMesh Tile),这样生成的二进制数据量会较少,分析的工作量会小很多
其次, 两个工具用相同的模型,以便二进制对比时能发现更多的相同点.便于确认相同的格式和数据段
<搭建的寻路模型>
<导出寻路模型的Obj文件>
<Unity里该寻路模型Bake的NavMesh,其中包含2个Tile,其中Tile1有1个poly,4个顶点,Tile2有4个poly,11个顶点>
运行Unity项目的Demo13场景,在Game窗口,点击DrawMesh,调用NavMesh.CalculateTriangulation接口,获取当前NavMesh的三角形信息,并画出相应的Mesh.在Hierarch界面选中生成的MeshObj,可以在Scene窗口看到当前NavMesh的三角形信息:
<画出NavMesh的三角形划分,可以看到Tile1有2个三角形,Tile2有7个三角形>
http://www.cnblogs.com/crazylights/p/5732078.html<在点击DrawMesh后,除了画出了NavMesh的三角形,也生成了NavMesh的各个顶点信息.可以在Hierarch窗口,看到19个顶点的位置数据(因为NavMesh只有11个顶点,所以这19个顶点中,有8个点是和其他点重叠的,这是用来确定三角形合并成poly的,参考NavMesh数据导出>
将模型(只取Recast的tile1数据做对比,所以去掉了tile2的正方体)导入Recast,调整CellSize=0.5和TileSize=112,使得Obj上生成两个tile.如下图
<Recast中的Obj寻路网格,有两个tile组成,其中Tile1有4个poly, 10个顶点)
二. 提取数据
1. 提取Unity NavMesh 二进制数据
在Unity里,设置以文本方式保存资源 -> Edit -> Project Setting -> Editor ->AssetSerialization-> Force Text
在Demo13.scene同级的Demo13目录下,找到NavMesh.assets 寻路网格数据文件
使用sublime 打开NavMesh.assets文件.查看文件内容
发现NavMesh一共有两个tile.文件里出现了两个m_MeshData,所以这个标签后面的十六进制位即为每个Tile的数据,查看每个m_MeshData的前8位十六进制位: 5641 4e44,即为Recastnavigation的DetourNavMesh.h里定义的Magic Num:
即"VAND"代表的十六进制位即为Tile数据开头的标志位,即5641 4e44(小端存储)
在Unity里,改设置以二进制方式保存资源 -> Edit -> Project Setting -> Editor ->AssetSerialization -> Force Binary
使用sublime 再次打开NavMesh.assets文件.查看文件的十六进制表示:
搜索十六进制5641 4e44,找到两个结果,把从第一个5641 4e44开始到第二个5641 4e44前的十六进制位提取出来,粘贴到Nodepad++中整理成每8位换行.然后复制到Excel里形成一列:
<整理Unity NavMesh十六进制数据示例,按上述方法,把NavMesh的Tile2也整理出来做参照>
2. 提取RecastNavigation NavMesh 二进制数据
在Recastnavigation中Build寻路网格后,点击Save.生成all_tiles_navmesh.bin文件.
用sublime打开该bin文件.搜索5641 4e44,把数据量较少的tile数据提取出来,像上述提取整理Unity寻路数据类似的方式整理在Excel里:
三. 解析数据
将Unity的NavMesh和Recast的十六进制数据提取之后,需要对数据进行解析
解析有两个线索:
一. 是Recast的代码中对各个字段的解析方式,因为Unity的NavMesh和Recast的NavMesh结构十分类似,这样可以很方便的推断NavMesh存在的对应的字段.两者的Tile数据都是以5641 4e44开头,因此也方便数据对齐比对.
二. 是Unity显示出来的NavMesh网格,可以提供一些参考数据,按上面第一步骤中观察到的tile的数量,poly的数量,顶点的数量以及顶点的位置,三角形的数量,等等,可以确定一些十六进制字段的含义,方便与Recast NavMesh做比对
因此首先在Codeblock中实现了从十六进制位转换成int类型和float类型数据的代码
在实现过程中,需要了解的知识有:
C++中各基本类型的内存存储长度.
C++中float和int,short,char类型在内存的存储方式(特别注意float浮点数存储尾数,指数,符号位的方式)
http://blog.****.net/vast_sea/article/details/8076934
http://www.cnblogs.com/dolphin0520/archive/2011/10/02/2198280.html
通过学习:
int ,float = 32位二进制(4字节),即8个16进制
short = 16位二进制(2字节),即4个16进制
char = 8位二进制(1字节),即2个16进制
PC intel为小端存储模式
Codeblocks中实现16进制转换int和float的C++代码:
(见最后7. CodeBlock 十六进制转int float项目)
将Unity的NavMesh的二进制数据,以8位为单位解析成int和float类型
并整理在Excel里做参考(Recast因为有源码去直接解析对应,不需要判断类型,所以不需要这一步骤):
四. 分析数据
有了NavMesh数据的int和float取值后,原NavMesh的数据十六进制数据就有了可读性.
Recast的源码DetourNavMesh.cpp的addTile函数是处理tile二进制数据到实际数据结构的算法.
在addTile里增加断点,调试每一步骤中,Recast是如何解析Mesh的二进制数据的.字段是如何对应的.
然后和NavMesh中的数据进行比对,以确定相同的字段
首先Recast先通过二进制数据构建了dtMeshHeader这个数据结构.
dtMeshHeader是Tile的数据格式头.包含了Tile里的各数据的长度以及寻路网格的一些基本信息,比如版本号,tile的x,y坐标等.
<dtMeshHeader的定义,各字段名称和长度等>
在Unity的tile信息里也应该有一个数据结构和dtMeshHeader对应,但是不一定和dtMeshHeader的定义字段完全相同.
因为C++在解析dtMeshHeader时肯定是逐个字段的去对应二进制数据.
因此,逐个解析字段和二进制的对应关系
magic字段: int类型,即8个十六进制,即:对应二进制数据 5641 4e44
即为DetourNavMesh.h中定义的 DT_NAVMESH_MAGIC
version字段: int类型 8个十六进制, 对应二进制 0700 0000
------
walkableHeight : float : 8个十六进制 : 0000 0040
在解析完dtMeshHeader后,继续按每种数据类型逐个解析二进制数据
最后可以得到每段二进制数据对应的字段名称:
<代码为dtMeshHeader之后的各字段数据的解析,根据已经解析的header中的各参数确定各字段的长度,然后按数据类型,解析为各个字段的数值>
Recast |
|||
数据类型 |
字段名 |
Navigation |
真实取值 |
int |
Magic |
5641 4e44 |
Magic |
int |
Version |
0700 0000 |
|
int |
x |
0100 0000 |
|
int |
y |
0000 0000 |
|
int |
layer |
0000 0000 |
|
int |
userId |
0000 0000 |
|
int |
polyCount |
0400 0000 |
|
int |
vertCount |
0a00 0000 |
|
int |
maxLinkCount |
1200 0000 |
|
int |
detailMeshCount |
0400 0000 |
|
int |
detailVertCount |
0000 0000 |
|
int |
detailTriCount |
0800 0000 |
|
int |
bvNodeCount |
0800 0000 |
|
int |
offMeshConCount |
0000 0000 |
|
int |
offMeshBase |
0400 0000 |
|
float |
walkableHeight |
0000 0040 |
|
float |
walkableRadius |
0000 003f |
0.5 |
float |
walkableClimb |
cdcc cc3e |
0.4 |
float |
bmin[0] |
0000 8041 |
|
float |
bmin[1] |
0000 00a5 |
-1.11E-16 |
float |
bmin[2] |
cdcc ec40 |
7.4 |
float |
bmax[0] |
0000 9042 |
|
float |
bmax[1] |
0000 0040 |
|
float |
bmax[2] |
9a99 7d42 |
63.4 |
float |
bvQuantFactor |
0000 0040 |
|
float |
verts[0].x |
0000 8041 |
|
float |
verts[0].y |
cdcc 4c3e |
0.2 |
float |
verts[0].z |
9a99 1142 |
36.4 |
float |
verts[1].x |
0000 dc41 |
27.5 |
float |
verts[1].y |
cdcc 4c3e |
0.2 |
float |
verts[1].z |
9a99 1142 |
36.4 |
float |
verts[2].x |
0000 1c42 |
|
float |
verts[2].y |
cdcc 4c3e |
0.2 |
float |
verts[2].z |
9a99 1142 |
36.4 |
float |
verts[3].x |
0000 1c42 |
|
float |
verts[3].y |
cdcc 4c3e |
0.2 |
float |
verts[3].z |
3333 eb41 |
29.4 |
float |
verts[4] |
0000 1c42 |
|
float |
verts[4] |
cdcc 4c3e |
0.2 |
float |
verts[4] |
3333 b741 |
22.9 |
float |
verts[5] |
0000 1c42 |
|
float |
verts[5] |
cdcc 4c3e |
0.2 |
float |
verts[5] |
6666 7e41 |
15.9 |
float |
verts[6] |
0000 1e42 |
39.5 |
float |
verts[6] |
cdcc 4c3e |
0.2 |
float |
verts[6] |
6666 2641 |
10.4 |
float |
verts[7] |
0000 1c42 |
|
float |
verts[7] |
cdcc 4c3e |
0.2 |
float |
verts[7] |
6666 0641 |
8.4 |
float |
verts[8] |
0000 dc41 |
27.5 |
float |
verts[8] |
cdcc 4c3e |
0.2 |
float |
verts[8] |
6666 0641 |
8.4 |
float |
verts[9] |
0000 8041 |
|
float |
verts[9] |
cdcc 4c3e |
0.2 |
float |
verts[9] |
6666 0641 |
8.4 |
int |
poly[0]->firstLink |
0000 0000 |
|
short*2 |
poly[0]->verts[0,1] |
0500 0600 |
5,6 |
short*2 |
poly[0]->verts[2,3] |
0700 0800 |
7,8 |
short*2 |
poly[0]->verts[4,5] |
0000 0000 |
0,0 |
short*2 |
poly[0]->neis[0,1] |
0000 0000 |
0,0 |
short*2 |
poly[0]->neis[2,3] |
0000 0300 |
0,3 |
short*2 |
poly[0]->neis[4,5] |
0000 0000 |
0,0 |
short char char |
poly[0]->flags,poly->vertCount,poly->areaAndType |
0100 0400 |
1,4,0 |
poly[1] |
0100 0000 |
||
poly[1] |
0100 0200 |
1,2 |
|
poly[1] |
0300 0000 |
3,0 |
|
poly[1] |
0000 0000 |
0,0 |
|
poly[1] |
0000 0000 |
0,0 |
|
poly[1] |
0400 0000 |
4,0 |
|
poly[1] |
0000 0000 |
0,0 |
|
poly[1] |
0100 0300 |
1,3,0 |
|
poly[2] |
0600 0000 |
||
poly[2] |
0400 0500 |
||
poly[2] |
0800 0900 |
||
poly[2] |
0000 0100 |
||
poly[2] |
0000 0100 |
||
poly[2] |
0000 0480 |
||
poly[2] |
0000 0400 |
||
poly[2] |
0100 0600 |
||
poly[3] |
0500 0000 |
||
poly[3] |
0100 0300 |
||
poly[3] |
0400 0000 |
||
poly[3] |
0000 0000 |
||
poly[3] |
0200 0000 |
||
poly[3] |
0300 0000 |
||
poly[3] |
0000 0000 |
||
poly[3] |
0100 0300 |
||
unsigned int |
link[0].ref |
0200 6001 |
|
unsigned int |
link[0].next |
ffff ffff |
|
unsigned char*4 |
link[0].edge,side,bmin,bmax |
03ff 0000 |
3,255,0,0 |
link |
0300 6001 |
||
link |
ffff ffff |
||
link |
02ff 0000 |
||
link |
0300 6001 |
||
link |
ffff ffff |
||
link |
05ff 0000 |
||
link |
0000 6001 |
||
link |
0200 0000 |
||
link |
01ff 0000 |
||
link |
0200 6001 |
||
link |
ffff ffff |
||
link |
02ff 0000 |
||
link |
0100 6001 |
||
link |
0400 0000 |
||
link |
00ff 0000 |
||
link |
0900 8001 |
||
link |
0300 0000 |
||
link |
0304 00ff |
||
link |
0000 0000 |
||
link |
0800 0000 |
||
link |
0000 0000 |
||
link |
0000 0000 |
||
link |
0900 0000 |
||
link |
0000 0000 |
||
link |
0000 0000 |
||
link |
0a00 0000 |
||
link |
0000 0000 |
||
link |
0000 0000 |
||
link |
0b00 0000 |
||
link |
0000 0000 |
||
link |
0000 0000 |
||
link |
0c00 0000 |
||
link |
0000 0000 |
||
link |
0000 0000 |
||
link |
0d00 0000 |
||
link |
0000 0000 |
||
link |
0000 0000 |
||
link |
0e00 0000 |
||
link |
0000 0000 |
||
link |
0000 0000 |
||
link |
0f00 0000 |
||
link |
0000 0000 |
||
link |
0000 0000 |
||
link |
1000 0000 |
||
link |
0000 0000 |
||
link |
0000 0000 |
||
link |
1100 0000 |
||
link |
0000 0000 |
||
link[17].ref |
0000 0000 |
||
link[17].next |
ffff ffff |
||
link[17].edge,side,bmin,bmax |
0000 0000 |
0,0,0,0 |
|
detailMeshes[0].vertBase |
0000 0000 |
||
detailMeshes[0].triBase |
0000 0000 |
||
detailMeshes[0].vertCount,triCount |
0002 0000 |
0,2 |
|
detailMeshes |
0000 0000 |
||
detailMeshes |
0200 0000 |
||
detailMeshes |
0001 0000 |
||
detailMeshes |
0000 0000 |
||
detailMeshes |
0300 0000 |
||
detailMeshes |
0004 0000 |
||
detailMeshes[3].vertBase |
0000 0000 |
||
detailMeshes[3].triBase |
0700 0000 |
||
detailMeshes[3].vertCount,triCount |
0001 0000 |
0,1 |
|
detailTris[0].p1,p2,p3, |
0300 0211 |
3,0,2,17 |
|
detailTris[1] |
0001 0205 |
||
detailTris[2] |
0200 0115 |
||
detailTris[3] |
0500 0411 |
||
detailTris[4] |
0001 0401 |
||
detailTris[5] |
0102 0401 |
||
detailTris[6] |
0203 0405 |
||
detailTris[7] |
0200 0115 |
2,0,1,21 |
|
bvTree[0].bmin[0],bmin[1] |
0000 0000 |
0,0 |
|
bvTree[0].bmin[2],bmax[0] |
0100 2f00 |
1,47 |
|
bvTree[0].bmax[1],bmax[2] |
0000 3a00 |
0,58 |
|
bvTree[0].i |
f9ff ffff |
-7 |
|
bvTree |
0000 0000 |
||
bvTree |
0100 2f00 |
||
bvTree |
0000 3a00 |
||
bvTree |
fdff ffff |
||
bvTree |
1700 0000 |
||
bvTree |
0100 2f00 |
||
bvTree |
0000 1100 |
||
bvTree |
0000 0000 |
||
bvTree |
0000 0000 |
||
bvTree |
0100 2e00 |
||
bvTree |
0000 3a00 |
||
bvTree |
0200 0000 |
||
bvTree |
1700 0000 |
||
bvTree |
1f00 2e00 |
||
bvTree |
0000 3a00 |
||
bvTree |
fdff ffff |
||
bvTree |
1700 0000 |
||
bvTree |
1f00 2e00 |
||
bvTree |
0000 3a00 |
||
bvTree |
0300 0000 |
||
bvTree |
1700 0000 |
||
bvTree |
2c00 2e00 |
||
bvTree |
0000 3a00 |
||
bvTree |
0100 0000 |
||
bvTree |
0000 0000 |
||
bvTree |
0000 0000 |
||
bvTree |
0000 0000 |
||
bvTree |
0000 0000 |
注意,从上表中的bvQuantFactor字段开始,即为除了heaer外的其他字段的数据范围.可以看到short类型长度为4个十六进制,char长度为2个十六进制.
例如:
十六进制 0500 0600 对应的是poly[0]->verts[0]和poly[0]->verts[1],poly的verts数组是short类型
因此: poly[0]->verts[0] = 0x0005 poly[0]->verts[1] = 0x0006 (小端模式存储)
注意小端模式存储: 每个字段确定了自己的十六进制范围后,需要以字节为单位(2个十六进制)高位的字节,存储在靠后位置.所以0500解析为short类型时,00字节在前,05直接在后,解析为0x0005 = 5(十进制)
十六进制 0100 0400 对应的是
short 类型 poly[0]->flags 对应: 0x0100 即 0x0001 = 1 (十进制)
char 类型 poly[0]->vertCount 对应: 0x04 即 0x04 = 4 (十进制)
char 类型 poly[0]->areaAndType 对应: 0x00 即 0x00 = 0 (十进制)
在对应Recast源码,单步调试确定了Recast的all_tiles_navmesh.bin文件内的tile的格式存储方式和对应关系后,可以研究NavMesh的Tile 十六进制序列的可能含义以及和Recast相对于的字段
将Unity的NavMesh的十六进制数据和Recast的相对比:
1. 5641 4e44 是Tile的标志位,Unity和Recast是相同的.
2. 1000 0000 在Recast中为0700 0000 是int类型的Version字段
将1000 0000 分别按float解析为2.24E-44,按int解析为16,从表面看,float数据似乎是无意义的
和Recast对比后,考虑Unity中也是int类型的Version字段.
(通过观察同样的十六进制解析为float和int的取值,可以估计字段的类型.确定其范围和对应字段)
3. 同理,分析了 x, y, layer字段.
4. 0100 0000 这个字段在Recast中为0000 0000 是int类型的userId字段.
将0100 0000 按float解析为bh, 按int解析为1.因此0100 0000 应该是int类型,取值为1.
这个字段按顺序应该是userId,但是,考虑到NavMesh和Recast相比,可能会多一些或者少一些字段,而且NavMesh的Tile1的poly数量为1(根据第一步中,在Unity中观察到的情况).因此这个数据也可能是userId的下一个字段polyCount,这个字段不确定,则向下继续分析
5. 0400 0000 按int解析=4, 这个字段在Recast中为0400 0000 是int类型的polyCount字段
但是NavMesh Tile1的poly数量为1,顶点数为4,所以这个字段不是Unity的polyCount字段,而很有可能是vertCount字段,而上面的0100 0000 很可能是NavMesh的polyCount字段,而不是uerId字段
因此可以推断,Unity NavMesh的header结构中,可能没有userId这一字段
所以,我们可以看到,在根据Recast的寻路网格数据结构推断Unity NavMesh的数据结构时不一定所有字段都是一一对应的,有些字段可能是Unity没有的,也可能是Unity独有的.这些字段的确定,就需要我们在Unity中观察到的NavMesh的特点和信息来确定.(在后面各个字段的确定中,需要巧妙的依据Unity中观察和导出的三角形数量,顶点数量,顶点的位置等信息来确定字段,比如Unity中导出的顶点的位置的x,y,z取值可以很容易在NavMesh的十六进制数据按float解析后找到对应关系,下表的v0,v1...)
6. 按上述方式解析Unity NavMesh的数据结构,最后,可以将Unity NavMesh的大部分字段解析出来,并和Recast对应字段相对应.
7. 因为Tile1数据比较简单(polyCount=1,detailMesh=1),所以在确定后面的poly, link时,无法得到更多的信息.很难确定字段的范围和字段的类型.这时候,可以导出Tile2的数据,并且把按Tile1数据已经分析出来的字段对应在Tile2上,然后观察Tile2和Tile1未分析的字段的长度区别和规律来确定和猜测字段的长度
8. 可以通过观察未确定数据的循环规律或者特定格式来确定字段的范围
如下图,从第一个0000 0000 开始,是detailMesh的数据,并且已知detailMesh数量为4个,detailMesh在Recast中的定义是dtPolyDetail.
需要确定Unity NavMesh的detailMesh的数据范围和字段
观察右边的数据,发现"0"是有规律的出现.两个0之间相隔2个数据,因此考虑每三行数据为一个detailMesh,到0200 0000 之前结束.
又因为Recast中的数据格式如下dtPolyDetail
十六进制 float解析 int解析
综上分析得出:
detailMesh[0].vertBase = 0000 0000 = 0;
detailMesh[0].triBase = 0000 0000 = 0;
detailMesh[0].vertCount = 0000 = 0;
detailMesh[0].triCount = 0100 = 0001 = 1;
----
detailMesh[3].vertBase = 0000 0000 = 0;
detailMesh[3].triBase = = = 5
detailMesh[3].vertCount = 0000 = 0;
detailMesh[3].triCount = 0200 = 0002 = 2;
9.char是2个16进制,short是4个16进制,因此如果按照8个16进制解析为float和int的结果都没有意义时,应该考虑按2个,或者4个16进制解析是否有意义
Recast |
NavMesh |
||||||||
数据类型 |
字段名 |
Navigation |
真实取值 |
数据类型 |
字段名 |
Tile 1 |
真实取值 |
按float解析 |
按int解析 |
int |
Magic |
5641 4e44 |
Magic |
int |
Magic |
5641 4e44 |
Magic |
825.021 |
|
int |
Version |
0700 0000 |
int |
Version |
1000 0000 |
2.24E-44 |
|||
int |
x |
0100 0000 |
int |
x |
ffff ffff |
-1 |
-1.#QNAN |
-1 |
|
int |
y |
0000 0000 |
int |
y |
0000 0000 |
||||
int |
layer |
0000 0000 |
int |
layer |
0000 0000 |
||||
int |
userId |
0000 0000 |
int |
polyCount |
0100 0000 |
bh |
|||
int |
polyCount |
0400 0000 |
int |
vertCount |
0400 0000 |
5.61E-45 |
|||
int |
vertCount |
0a00 0000 |
int |
detailMeshCount |
0100 0000 |
1.40E-45 |
|||
int |
maxLinkCount |
1200 0000 |
int |
detailVertCount |
0000 0000 |
||||
int |
detailMeshCount |
0400 0000 |
int |
detailTriCount |
0200 0000 |
2.80E-45 |
|||
int |
detailVertCount |
0000 0000 |
int |
bvNodeCount |
0200 0000 |
2 |
2.80E-45 |
||
int |
detailTriCount |
0800 0000 |
float |
bmin.x |
abaa 2ac2 |
-42.6667 |
-42.6667 |
-1037391189 |
|
int |
bvNodeCount |
0800 0000 |
float |
bmin.y |
0000 a0c0 |
-5 |
-5 |
-1063256064 |
|
int |
offMeshConCount |
0000 0000 |
float |
bmin.z |
0000 0000 |
||||
int |
offMeshBase |
0400 0000 |
float |
bmax.x |
0000 0000 |
||||
float |
walkableHeight |
0000 0040 |
float |
bmax.y |
9a99 1141 |
9.1 |
9.1 |
||
float |
walkableRadius |
0000 003f |
0.5 |
float |
bmax.z |
abaa 2a42 |
42.6667 |
42.6667 |
|
float |
walkableClimb |
cdcc cc3e |
0.4 |
float |
bvQuantFactor |
0000 c040 |
|||
float |
bmin[0] |
0000 8041 |
float |
v0.x |
0000 0000 |
||||
float |
bmin[1] |
0000 00a5 |
-1.11E-16 |
float |
v0.y |
c0aa aa3d |
0.0833335 |
0.0833335 |
|
float |
bmin[2] |
cdcc ec40 |
7.4 |
float |
v0.z |
5655 1342 |
36.8333 |
36.8333 |
|
float |
bmax[0] |
0000 9042 |
float |
v1.x |
0000 0000 |
||||
float |
bmax[1] |
0000 0040 |
float |
v1.y |
c0aa aa3d |
0.0833335 |
0.0833335 |
||
float |
bmax[2] |
9a99 7d42 |
63.4 |
float |
v1.z |
0000 0041 |
|||
float |
bvQuantFactor |
0000 0040 |
float |
v2.x |
5655 1dc2 |
-39.3333 |
-39.3333 |
-1038265002 |
|
float |
verts[0].x |
0000 8041 |
float |
v2.y |
c0aa aa3d |
0.0833335 |
0.0833335 |
||
float |
verts[0].y |
cdcc 4c3e |
0.2 |
float |
v2.z |
0000 0041 |
|||
float |
verts[0].z |
9a99 1142 |
36.4 |
float |
v3.x |
5655 1dc2 |
-39.3333 |
-39.3333 |
-1038265002 |
float |
verts[1].x |
0000 dc41 |
27.5 |
float |
v3.y |
c0aa aa3d |
0.0833335 |
0.0833335 |
|
float |
verts[1].y |
cdcc 4c3e |
0.2 |
float |
v3.z |
5655 1342 |
36.8333 |
36.8333 |
|
float |
verts[1].z |
9a99 1142 |
36.4 |
short*2 |
poly[0].verts[0,1] |
0000 0100 |
0,1 |
9.18E-41 |
|
float |
verts[2].x |
0000 1c42 |
short*2 |
poly[0].verts[2,3] |
0200 0300 |
2,3 |
2.76E-40 |
||
float |
verts[2].y |
cdcc 4c3e |
0.2 |
poly[0].verts[4,5] |
0000 0000 |
0,0 |
|||
float |
verts[2].z |
9a99 1142 |
36.4 |
poly[0].neis[0,1] |
0080 0000 |
32768,0 |
4.59E-41 |
||
float |
verts[3].x |
0000 1c42 |
poly[0].neis[2,3] |
0000 0000 |
0,0 |
||||
float |
verts[3].y |
cdcc 4c3e |
0.2 |
poly[0].neis[4,5] |
0000 0000 |
0,0 |
|||
float |
verts[3].z |
3333 eb41 |
29.4 |
poly[0]->flags |
0100 0000 |
1.40E-45 |
|||
float |
verts[4] |
0000 1c42 |
poly[0]->vertCount |
0400 0000 |
5.61E-45 |
||||
float |
verts[4] |
cdcc 4c3e |
0.2 |
detailMeshes[0].vertBase |
0000 0000 |
||||
float |
verts[4] |
3333 b741 |
22.9 |
detailMeshes[0].triBase |
0000 0000 |
||||
float |
verts[5] |
0000 1c42 |
detailMeshes[0].vertCount,triCount |
0000 0200 |
0,2 |
1.84E-40 |
|||
float |
verts[5] |
cdcc 4c3e |
0.2 |
detailTri[0].p0,p1 |
0300 0000 |
3,0 |
4.20E-45 |
||
float |
verts[5] |
6666 7e41 |
15.9 |
detailTri[0].p2,edagFlag |
0200 1100 |
2,17 |
1.56E-39 |
||
float |
verts[6] |
0000 1e42 |
39.5 |
detailTri[1].p0,p1 |
0000 0100 |
0,1 |
9.18E-41 |
||
float |
verts[6] |
cdcc 4c3e |
0.2 |
detailTri[1].p2,edagFlag |
0200 0500 |
2,5 |
4.59E-40 |
||
float |
verts[6] |
6666 2641 |
10.4 |
bvTree[0].bmin[0],bmin[1] |
1400 1e00 |
20,30 |
2.76E-39 |
||
float |
verts[7] |
0000 1c42 |
bvTree[0].bmin[2],bmax[0] |
3000 0001 |
48,256 |
2.35E-38 |
|||
float |
verts[7] |
cdcc 4c3e |
0.2 |
bvTree[0].bmax[1],bmax[2] |
2400 dd00 |
36,221 |
2.03E-38 |
||
float |
verts[7] |
6666 0641 |
8.4 |
bvTree[0].i |
0000 0000 |
||||
float |
verts[8] |
0000 dc41 |
27.5 |
bvTree |
0000 0000 |
||||
float |
verts[8] |
cdcc 4c3e |
0.2 |
bvTree |
0000 0000 |
||||
float |
verts[8] |
6666 0641 |
8.4 |
bvTree |
0000 0000 |
||||
float |
verts[9] |
0000 8041 |
bvTree |
0000 0000 |
|||||
float |
verts[9] |
cdcc 4c3e |
0.2 |
3402 0000 |
7.90E-43 |
||||
float |
verts[9] |
6666 0641 |
8.4 |
||||||
int |
poly[0]->firstLink |
0000 0000 |
|||||||
short*2 |
poly[0]->verts[0,1] |
0500 0600 |
5,6 |
||||||
short*2 |
poly[0]->verts[2,3] |
0700 0800 |
7,8 |
||||||
short*2 |
poly[0]->verts[4,5] |
0000 0000 |
0,0 |
||||||
short*2 |
poly[0]->neis[0,1] |
0000 0000 |
0,0 |
||||||
short*2 |
poly[0]->neis[2,3] |
0000 0300 |
0,3 |
||||||
short*2 |
poly[0]->neis[4,5] |
0000 0000 |
0,0 |
||||||
short char char |
poly[0]->flags,poly->vertCount,poly->areaAndType |
0100 0400 |
1,4,0 |
||||||
poly[1] |
0100 0000 |
||||||||
poly[1] |
0100 0200 |
1,2 |
|||||||
poly[1] |
0300 0000 |
3,0 |
|||||||
poly[1] |
0000 0000 |
0,0 |
|||||||
poly[1] |
0000 0000 |
0,0 |
|||||||
poly[1] |
0400 0000 |
4,0 |
|||||||
poly[1] |
0000 0000 |
0,0 |
|||||||
poly[1] |
0100 0300 |
1,3,0 |
|||||||
poly[2] |
0600 0000 |
||||||||
poly[2] |
0400 0500 |
||||||||
poly[2] |
0800 0900 |
||||||||
poly[2] |
0000 0100 |
||||||||
poly[2] |
0000 0100 |
||||||||
poly[2] |
0000 0480 |
||||||||
poly[2] |
0000 0400 |
||||||||
poly[2] |
0100 0600 |
||||||||
poly[3] |
0500 0000 |
||||||||
poly[3] |
0100 0300 |
||||||||
poly[3] |
0400 0000 |
||||||||
poly[3] |
0000 0000 |
||||||||
poly[3] |
0200 0000 |
||||||||
poly[3] |
0300 0000 |
||||||||
poly[3] |
0000 0000 |
||||||||
poly[3] |
0100 0300 |
||||||||
unsigned int |
link[0].ref |
0200 6001 |
|||||||
unsigned int |
link[0].next |
ffff ffff |
|||||||
unsigned char*4 |
link[0].edge,side,bmin,bmax |
03ff 0000 |
3,255,0,0 |
||||||
link |
0300 6001 |
||||||||
link |
ffff ffff |
||||||||
link |
02ff 0000 |
||||||||
link |
0300 6001 |
||||||||
link |
ffff ffff |
||||||||
link |
05ff 0000 |
||||||||
link |
0000 6001 |
||||||||
link |
0200 0000 |
||||||||
link |
01ff 0000 |
||||||||
link |
0200 6001 |
||||||||
link |
ffff ffff |
||||||||
link |
02ff 0000 |
||||||||
link |
0100 6001 |
||||||||
link |
0400 0000 |
||||||||
link |
00ff 0000 |
||||||||
link |
0900 8001 |
||||||||
link |
0300 0000 |
||||||||
link |
0304 00ff |
||||||||
link |
0000 0000 |
||||||||
link |
0800 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0900 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0a00 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0b00 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0c00 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0d00 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0e00 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0f00 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
1000 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
0000 0000 |
||||||||
link |
1100 0000 |
||||||||
link |
0000 0000 |
||||||||
link[17].ref |
0000 0000 |
||||||||
link[17].next |
ffff ffff |
||||||||
link[17].edge,side,bmin,bmax |
0000 0000 |
0,0,0,0 |
|||||||
detailMeshes[0].vertBase |
0000 0000 |
||||||||
detailMeshes[0].triBase |
0000 0000 |
||||||||
detailMeshes[0].vertCount,triCount |
0002 0000 |
0,2 |
|||||||
detailMeshes |
0000 0000 |
||||||||
detailMeshes |
0200 0000 |
||||||||
detailMeshes |
0001 0000 |
||||||||
detailMeshes |
0000 0000 |
||||||||
detailMeshes |
0300 0000 |
||||||||
detailMeshes |
0004 0000 |
||||||||
detailMeshes[3].vertBase |
0000 0000 |
||||||||
detailMeshes[3].triBase |
0700 0000 |
||||||||
detailMeshes[3].vertCount,triCount |
0001 0000 |
0,1 |
|||||||
detailTris[0].p1,p2,p3, |
0300 0211 |
3,0,2,17 |
|||||||
detailTris[1] |
0001 0205 |
||||||||
detailTris[2] |
0200 0115 |
||||||||
detailTris[3] |
0500 0411 |
||||||||
detailTris[4] |
0001 0401 |
||||||||
detailTris[5] |
0102 0401 |
||||||||
detailTris[6] |
0203 0405 |
||||||||
detailTris[7] |
0200 0115 |
2,0,1,21 |
|||||||
bvTree[0].bmin[0],bmin[1] |
0000 0000 |
0,0 |
|||||||
bvTree[0].bmin[2],bmax[0] |
0100 2f00 |
1,47 |
|||||||
bvTree[0].bmax[1],bmax[2] |
0000 3a00 |
0,58 |
|||||||
bvTree[0].i |
f9ff ffff |
-7 |
|||||||
bvTree |
0000 0000 |
||||||||
bvTree |
0100 2f00 |
||||||||
bvTree |
0000 3a00 |
||||||||
bvTree |
fdff ffff |
||||||||
bvTree |
1700 0000 |
||||||||
bvTree |
0100 2f00 |
||||||||
bvTree |
0000 1100 |
||||||||
bvTree |
0000 0000 |
||||||||
bvTree |
0000 0000 |
||||||||
bvTree |
0100 2e00 |
||||||||
bvTree |
0000 3a00 |
||||||||
bvTree |
0200 0000 |
||||||||
bvTree |
1700 0000 |
||||||||
bvTree |
1f00 2e00 |
||||||||
bvTree |
0000 3a00 |
||||||||
bvTree |
fdff ffff |
||||||||
bvTree |
1700 0000 |
||||||||
bvTree |
1f00 2e00 |
||||||||
bvTree |
0000 3a00 |
||||||||
bvTree |
0300 0000 |
||||||||
bvTree |
1700 0000 |
||||||||
bvTree |
2c00 2e00 |
||||||||
bvTree |
0000 3a00 |
||||||||
bvTree |
0100 0000 |
||||||||
bvTree |
0000 0000 |
||||||||
bvTree |
0000 0000 |
||||||||
bvTree |
0000 0000 |
||||||||
bvTree |
0000 0000 |
五. 总结
分析得出NavMesh的Tile 数据格式可能如下:
(需要继续验证)
int MagicNum = 0x5641 4e44;
int Version;
int x;
int y;
int layer;
int polyCount;
int vertCount;
int detailMeshCount;
int detailVertCount;
int detailTriCount;
int bvNodeCount;
float bmin[3]; //(x,y,z) 其中x,z坐标为Tile的右下角x/z平面坐标,y坐标确定了y方向的最小值
float bmax[3]; //(x,y,z) 其中x,z坐标为Tile的左上角x/z平面坐标,y坐标确定了y方向的最大值
float bvQuantFactor;
float verts[3 * vertCount]; //(x,y,z)
struct Poly[polyCount]
{
short verts[6];
short neis[6];
int flags;
int vertCount;
}
struct DetailMesh[detailMeshCount]
{
int vertBase;
int triBase;
short vertCount;
short triCount;
}
float detailVerts[3 * detailVertCount];
struct DetailTri[detailTriCount]
{
short[3] points; //三角形三个点的索引id
short edageFlag;
}
struct BvTree[bvNodeCount]
{
short bmin[3];
short bmax[3];
int i;
}
六. 相关文件
1. Unity项目
2. RecastNavigation
3. Excel 整理对比文件
4. Recast 导出网格文件
5. Unity Demo13 NavMesh.assets Binary Format
6. Unity Demo13 NavMesh.assets Text Format
7. CodeBlock 十六进制转int float项目