zoukankan      html  css  js  c++  java
  • 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行)。

    作者:yzwalkman
    转载请注明出处。
  • 相关阅读:
    vsftpd配置再次冲击Ubuntu之server篇
    update关联其他表批量更新数据
    丁丁的成长7
    Winform中使用PictureBox显示及修改数据库中的照片
    Apache HTTP Server 与 Tomcat 的三种连接方式
    丁丁的成长5
    tomcat的自动启动再次冲击Ubuntu之server篇
    再严重的感冒,马上就好【转】
    基本配置2被忽悠进了CentOS 6
    丁丁的成长6
  • 原文地址:https://www.cnblogs.com/yzwalkman/p/2920277.html
Copyright © 2011-2022 走看看