Ogre源代码浅析——Mesh文件结构及加载(三)

    MeshSerializer::importMesh()调用的MeshSerializerImpl::importMesh()(参见:http://www.cnblogs.com/yzwalkman/archive/2013/02/21/2920277.html Mesh文件结构及加载(二)第三段代码37行)展开如下:

 1     void MeshSerializerImpl::importMesh(DataStreamPtr& stream, Mesh* pMesh, MeshSerializerListener *listener)
 2     {
 3         // Determine endianness (must be the first thing we do!)
 4         determineEndianness(stream);
 5 
 6         // Check header
 7         readFileHeader(stream);
 8 
 9         unsigned short streamID;
10         while(!stream->eof())
11         {
12             streamID = readChunk(stream);
13             switch (streamID)
14             {
15             case M_MESH:
16                 readMesh(stream, pMesh, listener);
17                 break;
18             }
19 
20         }
21     }

    以上代码中的10-20行说明,一个Mesh文件可以有多个id值为M_MESH的chunk(参见:http://www.cnblogs.com/yzwalkman/archive/2013/02/20/2916953.html Mesh文件结构及加载(一))。对每个M_MESH的chunk的读取工作由readMesh函数来完成。readMesh函数展开如下:

 1  void MeshSerializerImpl::readMesh(DataStreamPtr& stream, Mesh* pMesh, MeshSerializerListener *listener)
 2     {
 3         // Never automatically build edge lists for this version
 4         // expect them in the file or not at all
 5         pMesh->mAutoBuildEdgeLists = false;
 6 
 7         // bool skeletallyAnimated
 8         bool skeletallyAnimated;
 9         readBools(stream, &skeletallyAnimated, 1);
10 
11         // Find all substreams
12         if (!stream->eof())
13         {
14             unsigned short streamID = readChunk(stream);
15             while(!stream->eof() &&
16                 (streamID == M_GEOMETRY ||
17                  streamID == M_SUBMESH ||
18                  streamID == M_MESH_SKELETON_LINK ||
19                  streamID == M_MESH_BONE_ASSIGNMENT ||
20                  streamID == M_MESH_LOD ||
21                  streamID == M_MESH_BOUNDS ||
22                  streamID == M_SUBMESH_NAME_TABLE ||
23                  streamID == M_EDGE_LISTS ||
24                  streamID == M_POSES ||
25                  streamID == M_ANIMATIONS ||
26                  streamID == M_TABLE_EXTREMES))
27             {
28                 switch(streamID)
29                 {
30                 case M_GEOMETRY:
31                     pMesh->sharedVertexData = OGRE_NEW VertexData();
32                     try {
33                         readGeometry(stream, pMesh, pMesh->sharedVertexData);
34                     }
35                     catch (Exception& e)
36                     {
37                         if (e.getNumber() == Exception::ERR_ITEM_NOT_FOUND)
38                         {
39                             // duff geometry data entry with 0 vertices
40                             OGRE_DELETE pMesh->sharedVertexData;
41                             pMesh->sharedVertexData = 0;
42                             // Skip this stream (pointer will have been returned to just after header)
43                             stream->skip(mCurrentstreamLen - MSTREAM_OVERHEAD_SIZE);
44                         }
45                         else
46                         {
47                             throw;
48                         }
49                     }
50                     break;
51                 case M_SUBMESH:
52                     readSubMesh(stream, pMesh, listener);
53                     break;
54                 case M_MESH_SKELETON_LINK:
55                     readSkeletonLink(stream, pMesh, listener);
56                     break;
57                 case M_MESH_BONE_ASSIGNMENT:
58                     readMeshBoneAssignment(stream, pMesh);
59                     break;
60                 case M_MESH_LOD:
61                     readMeshLodInfo(stream, pMesh);
62                     break;
63                 case M_MESH_BOUNDS:
64                     readBoundsInfo(stream, pMesh);
65                     break;
66                 case M_SUBMESH_NAME_TABLE:
67                     readSubMeshNameTable(stream, pMesh);
68                     break;
69                 case M_EDGE_LISTS:
70                     readEdgeList(stream, pMesh);
71                     break;
72                 case M_POSES:
73                     readPoses(stream, pMesh);
74                     break;
75                 case M_ANIMATIONS:
76                     readAnimations(stream, pMesh);
77                     break;
78                 case M_TABLE_EXTREMES:
79                     readExtremes(stream, pMesh);
80                     break;
81                 }
82 
83                 if (!stream->eof())
84                 {
85                     streamID = readChunk(stream);
86                 }
87 
88             }
89             if (!stream->eof())
90             {
91                 // Backpedal back to start of stream
92                 stream->skip(-MSTREAM_OVERHEAD_SIZE);
93             }
94         }
95 
96     }

     某些自定义的3D文件,会出现递归结构——比如在submesh中还可以定义submesh。读取这种结构的文件数据,就要依靠函数的递归调用。但Ogre的Mesh文件格式没有这么复杂的嵌套定义,故只需要在一个循环的状态机中即可实现所有数据的正确导入。15-88行即是这样一种循环状态机结构,这种程序结构是与Ogre的Mesh文件结构相对应的。

作者:yzwalkman
转载请注明出处。
原文地址:https://www.cnblogs.com/yzwalkman/p/2922077.html