他这个节点的值很有规律,大家发现没,主要的节点,如Mesh,SubMesh,Geometry,MeshSkeletonLink,MeshLOD这些主节点采用如0xX000,而在各个主节点下如SubMesh(0x4000)下的分支SubMeshOperation(0x4010),SubMeshBoneAssignment(0x4100),可以看到每个主Chunk之间可以有0x1000(4096)个分Chunk.主分支的值是0x1000的整数倍.分支Chunk也可以由他的值判断是那个主分支下的节点.
这个节点中很多部分都是和动画有关,在这里,我们先分析简单的Mesh,也就是不包含动画里的,第一张是一个典型意义上的无动画的Mesh结构.让我们根据第一张图来分析下.
Mesh文件首先是他的头文件,分别是short类型,用于检查是否是Mesh的节点0x1000,如果不是,说明此文件有误,然后是Mesh的版本信息.
然后就是Mesh块本身的信息,前面说过块包含了类型Mesh(0x3000),长度二个信息.然后是否是动画,在这里,是false.
如果Mesh和本身的SubMesh共享数据,先看一个不共享数据的模型,在OpenGL
OBJ模型的加载,在OBJ模型中,每一部分对应各自己的顶点,有各自的顶点索引.对应OBJ模型,我们可以想到Mesh的共享数据就是只有Mesh数据有顶点信息,而所有的SubMesh只持有对应Mesh数据的顶点索引信息.不共享数据就比较简单了,和OBJ模型一样,Mesh本身没有(不知有没本身有,但是子类不用的情况),而各个SubMesh保存自己的顶点信息与对应的顶点索引信息.一般来说共享数据时,Mesh本身才有Geometry(保存顶点信息)节点信息的.
接着上面,那么下一Chunk块应该是SubMesh,这块里首先读取对应的材质文件,然后加载材质到对应的Submesh中,然后读取是否和Mesh共享数据,如果是False的话,接着读取顶点索引信息和顶点信息,就是上图中第一个标颜色框的部分.如果是True的话,就只读取顶点索引信息.而相应顶点数据在Mesh中的Geometry节点中,这个节点读取数据就是上图中第一个标颜色框去掉前三行的部分.
针对前面标颜色框的那一部分,简单讲解下,对比Axiom
3D:数据绑定基本流程,
前三行就是反序列化IndexData(顶点索引信息),另外的部分就是顶点信息VertexData,在这里面又分成VertexDeclaration的反序列化,里面包含VertexDeclaration中的VertexElement的各个属性的反序列化,五个short类型,可以看到VertexElement
Chunk长度是16,也就是5*2+(2+4)的长度,2+4就是前面提到的这个Chunk块用int表示的长度,这个长度包含他自己,就是上面说的sizeof(ushort)+sizeof(int)=6.VertexDeclaration
Chunk块的长度就等于VertexElement的个数3*16+6=54.接着VertexDeclaration的序列化后就是VertexData本身的数据反序列化,对应的是vertexbuffer
chunk,这块里首先是绑定索引,然后是每个顶点包含数据总字节长度,对比上图这里是32位(在顶点信息里存的都是单精度浮点数据),意思有八个浮点数据(其实就是V3N3T2),.反序列化数据总长就是58*32=1856.然后就是VertexBufferData
chunk块,在此块里存储着所有顶点让我们来检查一下.得到VertexBufferData
chunk块总长度为1862.然后验证1862=6+1856,正确.在此块后面还有二个块,一个指定数据的组织形式,如是三角形还是四边形或是一点等,后面一块指定这个Mesh的包围盒和半径.
接着我们看MeshLOD
Chunk,这个Chunk里,首先读取什么方式启用Lod,然后是Lod级别,然后指出是否手动生成Lod.如果是manual
Lod,如果是那么就每lodlevel加载对应的manmal
name,如果不是,就需要在每个lodlevel里就每个SubMesh读取MeshLODGenerated
Chunk块,然后在此块读取第一个颜色块里的对应的IndexData,VertexData的数据.
针对Mesh的反序列化,有助于我们理解Mesh的结构,或者以后我们要自定义一些Mesh与别的格式文件的互转,熟悉Mesh文件结构还是有必要的.
PS:每次看到别人的开源代码,里面都是非常清晰,没啥冗余代码.不知到这种水平需要多久.