ogre 引擎 框架追踪 第三章 资源加载之虚加载

来源:互联网 发布:淘宝库房分拣员累吗 编辑:程序博客网 时间:2024/06/05 19:38

前序 ogre 引擎 框架追踪 第二章 初始化

前面两章已经创建root、加载dll、创建渲染系统、创建渲染窗口。这章,我们该往整个框架里塞东西了。ogre1.8用的单线程,不支持后台加载。关于资源的操作就是:
创建资源管理器->继承不同资源管理器的创建->向资源管理器添加路径->初始化已添加路径的资源->加载资源->渲染资源。
前面两步已经在前面实现,接下来的开始添加路径。

1、ogre资源的路径添加

ogre中有两种方式实现路径加载,一种傻瓜式加载,直接传入一个cfg文件名称,解析了就把解析的资源目录添加到资源管理器中,另一种就是手动添加,直接调用资源管理器向里面添加资源。

resouce.cfg

第一种,傻瓜式的。
先看下resouce.cfg里的内容

[Essential] #资源分组名称,这个里面是ogre自带的最基础的资源#这里有traymanager里所需的资源,包括overlay、鼠标、字体Zip=../../media/packs/SdkTrays.zip  Zip=../../media/packs/profiler.zip  FileSystem=../../media/thumbnails  # Common sample resources needed by many of the samples.# Rarely used resources should be separately loaded by the# samples which require them.[Popular]FileSystem=../../media/fontsFileSystem=../../media/materials/programsFileSystem=../../media/materials/scriptsFileSystem=../../media/materials/texturesFileSystem=../../media/materials/textures/nvidiaFileSystem=../../media/modelsFileSystem=../../media/particleFileSystem=../../media/DeferredShadingMediaFileSystem=../../media/PCZAppMediaFileSystem=../../media/RTShaderLibFileSystem=../../media/RTShaderLib/materialsFileSystem=../../media/materials/scripts/SSAOFileSystem=../../media/materials/textures/SSAOZip=../../media/packs/cubemap.zipZip=../../media/packs/cubemapsJS.zipZip=../../media/packs/dragon.zipZip=../../media/packs/fresneldemo.zipZip=../../media/packs/ogretestmap.zipZip=../../media/packs/ogredance.zipZip=../../media/packs/Sinbad.zipZip=../../media/packs/skybox.zip[General]FileSystem=../../media# Materials for visual tests[Tests]FileSystem=../../media/../../Tests/Media[Popular] Zip=../../media/packs/NxOgre.zip 

结构上就是:
[分组组名]
Zip=**.zip #zip文件目录
FileSystem=** #文件夹

解析并加载cfg文件

void RenderScene::setupResources(Ogre::String cfgFile){    ConfigFile cf;    cf.load(cfgFile);//加载并解析    // Go through all sections & settings in the file    ConfigFile::SectionIterator seci = cf.getSectionIterator();    String secName, typeName, archName;    while (seci.hasMoreElements())    {        secName = seci.peekNextKey();        ConfigFile::SettingsMultiMap *settings = seci.getNext();        ConfigFile::SettingsMultiMap::iterator i;        for (i = settings->begin(); i != settings->end(); ++i)        {            typeName = i->first;            archName = i->second;            //资源管理器中添加资源路径            ResourceGroupManager::getSingleton().addResourceLocation(                archName, typeName, secName);        }    }}

.cfg文件的解析,最终的实现:

        std::ifstream fp;        // Always open in binary mode        fp.open(filename.c_str(), std::ios::in | std::ios::binary);        if(!fp)            OGRE_EXCEPT(            Exception::ERR_FILE_NOT_FOUND, "'" + filename + "' file not found!", "ConfigFile::load" );        // Wrap as a stream,转换成ogredatastream,代码不难,就是用windows的方法获取大小,再用模板类转换成datasteam,可以自己看。        DataStreamPtr stream(OGRE_NEW FileStreamDataStream(filename, &fp, false));        load(stream, separators, trimWhitespace);//继续,根儿上的解析

根儿上的解析

void ConfigFile::load(const DataStreamPtr& stream, const String& separators,         bool trimWhitespace)    {        clear();//清理之前加载的东西        String currentSection = StringUtil::BLANK;        SettingsMultiMap* currentSettings = OGRE_NEW_T(SettingsMultiMap, MEMCATEGORY_GENERAL)();//用ogre_new智能指针新建,不用担心释放了就        mSettings[currentSection] = currentSettings;        /* Process the file line for line */        String line, optName, optVal;        while (!stream->eof())        {            line = stream->getLine();//读取一行并返回            /* Ignore comments & blanks,不管#开头的(注释)和@开头的 */            if (line.length() > 0 && line.at(0) != '#' && line.at(0) != '@')            {                if (line.at(0) == '[' && line.at(line.length()-1) == ']')//读取"[]"内的为组名                {                    // Section                    currentSection = line.substr(1, line.length() - 2);                    SettingsBySection::const_iterator seci = mSettings.find(currentSection);                    if (seci == mSettings.end())                    {                        currentSettings = OGRE_NEW_T(SettingsMultiMap, MEMCATEGORY_GENERAL)();                        mSettings[currentSection] = currentSettings;                    }                    else                    {                        currentSettings = seci->second;                    }                 }                else//不是组名的添加到当前组中                {                    Ogre::String::size_type separator_pos = line.find_first_of(separators, 0);                    if (separator_pos != Ogre::String::npos)                    {                        optName = line.substr(0, separator_pos);//等号前的name                        Ogre::String::size_type nonseparator_pos = line.find_first_not_of(separators, separator_pos);                        optVal = (nonseparator_pos == Ogre::String::npos) ? "" : line.substr(nonseparator_pos);//等号后的value                        if (trimWhitespace)                        {                            StringUtil::trim(optVal);                            StringUtil::trim(optName);                        }                        currentSettings->insert(SettingsMultiMap::value_type(optName, optVal));//当前组中添加name和value                    }                }            }        }    }

添加到资源管理器

解析出的信息通过addResourceLocation添加到资源管理器中,添加过程:
获取resoucegroup->有则获取无则创建->文件管理器加载

//获取group ResourceGroup* grp = getResourceGroup(resGroup);        if (!grp)        {            createResourceGroup(resGroup);            grp = getResourceGroup(resGroup);        }        //锁资源分组        OGRE_LOCK_MUTEX(grp->OGRE_AUTO_MUTEX_NAME) // lock group mutex        // Get archive        Archive* pArch = ArchiveManager::getSingleton().load( name, locType );        // Add to location list        ResourceLocation* loc = OGRE_NEW_T(ResourceLocation, MEMCATEGORY_RESOURCE);        loc->archive = pArch;        loc->recursive = recursive;        grp->locationList.push_back(loc);        // Index resources        StringVectorPtr vec = pArch->find("*", recursive);//获取文件路径中所有文件        for( StringVector::iterator it = vec->begin(); it != vec->end(); ++it )            grp->addToIndex(*it, pArch);//通过文件名保存archive。已判断资源存在不存在、文件对象是啥等等。

先解析ArchiveManager::getSingleton().load这个函数,实现由注册的文件工厂(文件类型)根据文件路径创建文件并加载
其中核心代码:

 ArchiveFactoryMap::iterator it = mArchFactories.find(archiveType);//前面root创建时我们已经注册过FileSystemArchiveFactory、ZipArchiveFactory、EmbeddedZipArchiveFactory            if (it == mArchFactories.end())              。。。              //没找到就报错。            pArch = it->second->createInstance(filename);//创建文件对象            pArch->load();  //加载            mArchives[filename] = pArch;

其中FileSystemArchive的load代码如下

        OGRE_LOCK_AUTO_MUTEX        String testPath = concatenate_path(mName, "__testwrite.ogre");        std::ofstream writeStream;        writeStream.open(testPath.c_str());        if (writeStream.fail())            mReadOnly = true;        else        {            mReadOnly = false;            writeStream.close();            ::remove(testPath.c_str());        }

我的妈呀,发现里面就是虚晃一枪,就是检查了下路径存在不存在,是不是只读,别的啥也没干啊
再看下ZipArchive的load

OGRE_LOCK_AUTO_MUTEX        if (!mZzipDir)        {            zzip_error_t zzipError;            mZzipDir = zzip_dir_open_ext_io(mName.c_str(), &zzipError, 0, mPluginIo);//打开            checkZzipError(zzipError, "opening archive");            // Cache names            ZZIP_DIRENT zzipEntry;            while (zzip_dir_read(mZzipDir, &zzipEntry))//读取            {                FileInfo info;                info.archive = this;                // Get basename / path                StringUtil::splitFilename(zzipEntry.d_name, info.basename, info.path);                info.filename = zzipEntry.d_name;                // Get sizes                info.compressedSize = static_cast<size_t>(zzipEntry.d_csize);                info.uncompressedSize = static_cast<size_t>(zzipEntry.st_size);                // folder entries                if (info.basename.empty())                {                    info.filename = info.filename.substr (0, info.filename.length () - 1);                    StringUtil::splitFilename(info.filename, info.basename, info.path);                    info.compressedSize = size_t (-1);                }                mFileList.push_back(info);//添加zip中的内容到zip archive的文件列表中            }        }

zip的倒是干了点事儿,那就是读取zip中文件列表并保存,以备后期真正的加载。

在虚加载之后,就是把路径中所有文件及对应的archive对象保存,以备后面使用。

简单描述虚加载就是:读取文件路径、zip,添加到各自的group,并且保存里面的文件与archive对象的对应。
虚加载之后,就是资源的初始化,下一章开始。

0 0