Ogre源代码浅析——Mesh文件结构及加载(二)
Ogre中的Mesh类对应着渲染所需的模型网格,其数据来自于Mesh文件。调用SceneManager::createEntity()时,Ogre会自动创建Mesh类对象,并从指定的Mesh文件中读取相应模型数据。createEntity()将形成以下call stack。
1 SceneManager::createEntity() 2 || 3 \/ 4 5 ... ... 6 7 || 8 \/ 9 MeshManager::load() 10 || 11 \/ 12 Resource::load() 13 || 14 \/ 15 Mesh::loadImpl()
其中,Mesh::loadImpl()函数展开后为:
1 void Mesh::loadImpl() 2 { 3 MeshSerializer serializer; 4 serializer.setListener(MeshManager::getSingleton().getListener()); 5 6 // If the only copy is local on the stack, it will be cleaned 7 // up reliably in case of exceptions, etc 8 DataStreamPtr data(mFreshFromDisk); 9 mFreshFromDisk.setNull(); 10 11 if (data.isNull()) { 12 OGRE_EXCEPT(Exception::ERR_INVALID_STATE, 13 "Data doesn't appear to have been prepared in " + mName, 14 "Mesh::loadImpl()"); 15 } 16 17 serializer.importMesh(data, this); 18 19 /* check all submeshes to see if their materials should be 20 updated. If the submesh has texture aliases that match those 21 found in the current material then a new material is created using 22 the textures from the submesh. 23 */ 24 updateMaterialForAllSubMeshes(); 25 }
Ogre将以二进制方式保存的外部数据描述为数据流,并以串行的方式逐字节读取数据流中数据。为此,Ogre专门引入了DataStream类和Serializer类,DataStream类对应着数据流概念,Serializer类对应着串行器。不同性质的数据流需要通过不同的串行器来帮助读取,MeshSerializer作为Serializer的派生类,主要用来读取Mesh文件中的数据。MeshSerializer是对网格数据流串行器的抽象,其作用在第一段代码17行中体现,17行代码展开为:
1 void MeshSerializer::importMesh(DataStreamPtr& stream, Mesh* pDest) 2 { 3 determineEndianness(stream); 4 5 // Read header and determine the version 6 unsigned short headerID; 7 8 // Read header ID 9 readShorts(stream, &headerID, 1); 10 11 if (headerID != HEADER_CHUNK_ID) 12 { 13 OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "File header not found", 14 "MeshSerializer::importMesh"); 15 } 16 // Read version 17 String ver = readString(stream); 18 // Jump back to start 19 stream->seek(0); 20 21 // Find the implementation to use 22 MeshSerializerImpl* impl = 0; 23 for (MeshVersionDataList::iterator i = mVersionData.begin(); 24 i != mVersionData.end(); ++i) 25 { 26 if ((*i)->versionString == ver) 27 { 28 impl = (*i)->impl; 29 break; 30 } 31 } 32 if (!impl) 33 OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Cannot find serializer implementation for " 34 "mesh version " + ver, "MeshSerializer::importMesh"); 35 36 // Call implementation 37 impl->importMesh(stream, pDest, mListener); 38 // Warn on old version of mesh 39 if (ver != mVersionData[0]->versionString) 40 { 41 LogManager::getSingleton().logMessage("WARNING: " + pDest->getName() + 42 " is an older format (" + ver + "); you should upgrade it as soon as possible" + 43 " using the OgreMeshUpgrade tool."); 44 } 45 46 }
由于不同版本的的Mesh文件有不同的格式(参见:http://www.cnblogs.com/yzwalkman/archive/2013/02/20/2916953.html Ogre源代码浅析——Mesh文件结构及加载(一)),Ogre又以Serializer为基类派生出了MeshSerializerImpl、MeshSerializerImpl_v1_41、MeshSerializerImpl_v1_4、MeshSerializerImpl_v1_3、MeshSerializerImpl_v1_2等类,根据网格数据流进行读取和解析的具体工作是由MeshSerializerImpl及其派生类对象来完成的。在第二段代码的MeshSerializer::importMesh()函数中,Ogre首先会根据网格文件的版本号找到相应的Mesh串行器(23-31行),然后再用具体的MeshSerializerImpl类对象进行网格数据的实际导入(37行)。
posted on 2013-02-21 14:34 yzwalkman 阅读(2818) 评论(0) 编辑 收藏 举报