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文件结构相对应的。