ogre 学习笔记 - Day 4

ogre 学习笔记 - Day 4


由于电脑C盘硬盘坏了,重新买了硬盘,重装系统,耽误了两天。


先回顾之前SampleBrowser的学习, 回忆一下。

SamplerBrowser加载了一些Sample资源,然后生成UI,通过点击选择Sample。
这里就出现了3个点

  • 如何加载资源
  • 如何创建UI
  • 如何加载场景

UI属于组件,暂时不管它。先看加载资源以及加载场景。

资源加载

Sample* loadSamples()
{
    Ogre::ConfigFile cfg;
#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
    // ...
#else
    cfg.load(mFSLayer->getConfigFilePath("samples.cfg"));
#endif
}

只看 Windows部分,首先,通过FileSystemLayer::getConfigFilePath 加载了一个配置文件。但是这个配置文件只有一个名称,它存放在哪呢?
通过vscode ctrl+p 查找文件,发现好多个。都打开看一下,发现都是一样的内容.

SampleFolder=.
SamplePlugin=DefaultSamples
#SamplePlugin=PlayPenTests

这个格式很像 .ini [key=value].
根据名称猜测,SampleFolder=. 是说Sample的文件夹在应用同级目录。SamplePlugin 不知道是什么意思。

问题来了,只有一个名字,怎么知道是哪个呢?

Ogre::String getConfigFilePath(Ogre::String filename) const
{
    // look for the requested file in several locations:
    
    // 1. in the writable path (so user can provide custom files)
    Ogre::String path = getWritablePath(filename);
    if (fileExists(path))
        return path;
    
    // 2. in the config file search paths
    for (const String& cpath : mConfigPaths)
    {
        path = cpath + filename;
        if (fileExists(path))
            return path;
    }
    
    // 3. fallback to current working dir
    return filename;
}

首先,寻找可写路径

Ogre::String getWritablePath(const Ogre::String& filename) const
{
    return mHomePath + filename;
}

出现了一个 mHomePath ,调试发现,它是一个不存在的路径。

然后,找 configPaths。

看看 homepath,configpath是如何赋值的。

  • HomePath

            void setHomePath(const Ogre::String &path){
                mHomePath = path;
            }
    

    一眼看见 setHomePath函数,调试竟然没运行到!无奈,全局搜索吧。

    void FileSystemLayer::prepareUserHome(const Ogre::String& subdir)
    {
        // fill mHomePath
    #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
        WCHAR wpath[MAX_PATH];
        if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL, 0, wpath)))
            widePathToOgreString(mHomePath, wpath);
    #elif OGRE_PLATFORM == OGRE_PLATFORM_WINRT
        widePathToOgreString(mHomePath, Windows::Storage::ApplicationData::Current->LocalFolder->Path->Data());
    #endif
    
        if(!mHomePath.empty())
        {
            mHomePath += '\\' + subdir + '\\';
            // create release subdir
            if (!createDirectory(mHomePath))
            {
                // couldn't create directory, fall back to current working dir
                mHomePath.clear();
            }
        }
    }
    
    FileSystemLayer(const Ogre::String& subdir)
    {
        // determine directories to search for config files
        getConfigPaths();
        // prepare write location in user directory
        prepareUserHome(subdir);
    }
    
    ApplicationContextBase::ApplicationContextBase(const Ogre::String& appName)
    {
        mAppName = appName;
        mFSLayer = new Ogre::FileSystemLayer(mAppName);
    
    // ...
    }
    

    hOME PATH 通过 SHGetFolderPathW(NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE,…)拿到用户的文档路径,然后加上应用的名,组成的路径。例如:C:/Users/xxx/Documents/SampleBrowser/

  • configPaths

        void FileSystemLayer::getConfigPaths()
        {
    #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            // try to determine the application's path
            String appPath = getModulePath(false);
    #elif OGRE_PLATFORM == OGRE_PLATFORM_WINRT
            Ogre::String appPath;
            widePathToOgreString(appPath, Windows::ApplicationModel::Package::Current->InstalledLocation->Path->Data());
    #endif
    
            // use application path as config search path
            if (!appPath.empty())
                mConfigPaths.push_back(appPath + '\\');
    #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            // look relative to the DLL according to PIP structure
            mConfigPaths.push_back(StringUtil::normalizeFilePath(getModulePath(true)+"/../../../bin/"));
    #endif
        }
    
  1. 应用所在路径(SampleBrowser的路径)

  2. dll所在的路径

    按照这个思路,就能找到真正使用的samples.cfg了。
    路径是按照顺序查找的,那么当文件重名时,就容易找错了。

读取配置文件内容

Ogre::String sampleDir = cfg.getSetting("SampleFolder");        // Mac OS X just uses Resources/ directory
Ogre::StringVector sampleList = cfg.getMultiSetting("SamplePlugin");
Ogre::String startupSampleTitle = cfg.getSetting("StartupSample");
// loop through all sample plugins...
for (Ogre::StringVector::iterator i = sampleList.begin(); i != sampleList.end(); i++)
{
    try   // try to load the plugin
    {
#ifdef OGRE_STATIC_LIB
        // ...
#else
        mRoot->loadPlugin(sampleDir + *i);
#endif
    }
    catch (Ogre::Exception& e)   // plugin couldn't be loaded
    {
        Ogre::LogManager::getSingleton().logError(e.what());
        unloadedSamplePlugins.push_back(sampleDir + *i);
        continue;
    }
}

读取数据之后,发现,配置中的SamplePlugin=DefaultSamples,竟然通过loadPlugin的方式加载,也就是说它把sample当成了插件!按照它的plugin的操作,按照名称导入DLL。所以,按名称找到工程当中的DefaultSamples. 就是它了。打开DefaultSamples,发现所有sample的代码。

既然把Sample当成了插件,那就不需要再深入探究了。回过头看如何加载场景。

场景加载

要加载场景,必然要new 场景对象,在sample的构造函数里下个断点。运行场景函数 runSamle下一个断点。运行发现

DefaultSamplesPlugin::DefaultSamplesPlugin()  : SamplePlugin("DefaultSamplesPlugin")
{
    addSample(new Sample_AtomicCounters);
    addSample(new Sample_BezierPatch);
    // ...
}

加载插件时,new了很多场景

任选一个场景,点击start。进入 runSample.

        virtual void runSample(Sample* s)
{
    // ...
    s->_setup(mWindow, mFSLayer, mOverlaySystem);   // start new sample
    // ...
}


virtual void _setup(Ogre::RenderWindow* window, Ogre::FileSystemLayer* fsLayer, Ogre::OverlaySystem* overlaySys)
{
    Sample::_setup(window, fsLayer, overlaySys);

    if(mTrayMgr)
        mControls.reset(new AdvancedRenderControls(mTrayMgr.get(), mCamera));
}
    virtual void _setup(Ogre::RenderWindow* window, Ogre::FileSystemLayer* fsLayer, Ogre::OverlaySystem* overlaySys)
    {
        mOverlaySystem = overlaySys;
        mWindow = window;

        mFSLayer = fsLayer;

        locateResources();
        createSceneManager();
        setupView();

        mCameraMan.reset(new CameraMan(mCameraNode));   // create a default camera controller

        loadResources();
        mResourcesLoaded = true;
        setupContent();
        mContentSetup = true;

        mDone = false;
    }
// BSP.h
void loadResources()
    {
        /* NOTE: The browser initialises everything at the beginning already, so we use a 0 init proportion.
           If you're not compiling this sample for use with the browser, then leave the init proportion at 0.7. */
        mTrayMgr->showLoadingBar(1, 1, 0);

        // associate the world geometry with the world resource group, and then load the group
        ResourceGroupManager& rgm = ResourceGroupManager::getSingleton();
        rgm.setCustomStagesForResourceGroup("BSPWorld", mSceneMgr->estimateWorldGeometry("maps/oa_rpg3dm2.bsp"));
        rgm.initialiseResourceGroup("BSPWorld");
        rgm.loadResourceGroup("BSPWorld");
        // one would register a ResourceGroupListener for this, if we were not to call it right away
        mSceneMgr->setWorldGeometry("maps/oa_rpg3dm2.bsp");

        mTrayMgr->hideLoadingBar();
    }

与前几天所知的一样,在 setup里,最终进入 loadResources(),setupContent()。
找到了sample的创建/加载/运行的方法,就可以对每一个sample分别进行学习了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值