Axiom3D:Ogre中Mesh文件格式分析(一)

     在Axiom3D,或者说是Ogre的mesh的文件格式我们可能通过代码反推出相关格式,相关过程本来我是直接写的,后面发现相关流程写完后,我自己都看晕了,然后我就把一些过程用Execl整理出来,发现过程清晰多了,如下这张图:

     这图是导入一个简单的mesh文件(没有包含动画)根据代码反推出的相关结构,这个Mesh文件的版本是1.30,不同的mesh版本格式略有不同,但是不会相差太大.

     首先针对上面的图中一些需要注意的地方说下,其中上面的类型为Chunk的表示一个用ushort表示的类型,和这个Chunk块用int表示的长度,这个长度包含他自己,就是上面说的sizeof(ushort)+sizeof(int)=6.其中的Bool类型,就是一个字节,因为在C++里有时会把bool用int表示,这里不一样.就是C#里的一个字节.在标识红色的地方,就是把上面从IndexCount到Vertexbuff在读取一遍.这里关于Axiom中的数据组织可以看Axiom 3D:数据绑定基本流程,里面对于VertexData,IndexData都有介绍,这里的流程就是填充这二个对象.

     Axiom3D中的mesh文件是二进制的,直接用文本打开全是乱码,虽然不像XML,文本等格式清晰易读.但是他本身的组织非常有条理,不是有个工具OgreXmlConverter,在看了相关代码后,我个人认为转成XML的难度一点不大,他本身就是用Chunk块组成了如树这种结构,因此在这个里面,最重要是各个Chunk块,如下是各块的一些信息.

  他这个节点的值很有规律,大家发现没,主要的节点,如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:每次看到别人的开源代码,里面都是非常清晰,没啥冗余代码.不知到这种水平需要多久.

posted @ 2014-03-14 01:06  天天不在  阅读(4740)  评论(0编辑  收藏  举报