ogre 学习笔记 - Day 3

这篇博客详细记录了学习Ogre3D SampleBrowser的过程,从WinMain入口开始,分析了SampleBrowser如何创建窗口、初始化UI,并着重探讨了createWindow函数在不同平台上的实现。在SampleBrowser的setup过程中,发现了UI的加载与资源管理,以及如何启动初始场景。同时,提出了UI更新与Ogre渲染流程的关系这一疑问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ogre 学习笔记 - Day 3


从之前的学习中,对ogre有了一些基本的认知。现在可以去尝试看看SampleBrowser了。

SampleBrowser

  • 找到程序入口 WinMain,WinMain里面除去一些七七八八的只剩两行

    OgreBites::SampleBrowser brows (nograb, startUpSampleIdx);
    brows.go();
    

    看看类关系

    class SampleBrowser : public SampleContext, public TrayListener
    
    class SampleContext : public ApplicationContext, public InputListener
    

    通过昨天的学习,知道 ApplicationContext 继承自 FrameListener。
    InputListener 响应设备输入事件,TrayListener响应UI事件。
    粗略看看 SampleBrowser, SampleContext 发现重载了很多事件响应。
    这其中发现重载了一个比较奇怪的函数 createWindow

    virtual NativeWindowPair createWindow(const Ogre::String& name, uint32_t w, uint32_t h, Ogre::NameValuePairList miscParams)
            {
    #if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID
                // ...
    #endif
                NativeWindowPair res = ApplicationContext::createWindow(name, w, h, miscParams);
    
    #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
                // ...
    #endif
    
                return res;
            }
    

    这个函数对不同的平台做了一些不同的设置,调用了父类的 ApplicationContext::createWindow。

    既然可以重载createWindow

    virtual NativeWindowPair
        createWindow(const Ogre::String& name, uint32_t w = 0, uint32_t h = 0,
                     Ogre::NameValuePairList miscParams = Ogre::NameValuePairList());
    
    struct NativeWindowPair
    {
        Ogre::RenderWindow* render;
        NativeWindowType* native;
    };
    

    createWindow 返回的是一个pair,包含 RenderWindow, NativeWindowType。

    调试一下,看看 createWinow 都做了什么。
    最终会进入到 ApplicationContextSDL::createWindow

    NativeWindowPair ApplicationContextSDL::createWindow(const Ogre::String& name, Ogre::uint32 w, Ogre::uint32 h, Ogre::NameValuePairList miscParams)
    {
        NativeWindowPair ret = {NULL, NULL};
    
        if(!SDL_WasInit(SDL_INIT_VIDEO)) {
            SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER);
        }
        
        // ...
        
        int flags = p.useFullScreen ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_RESIZABLE;
        int d = Ogre::StringConverter::parseInt(miscParams["monitorIndex"], 1) - 1;
        ret.native =
            SDL_CreateWindow(p.name.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(d),
                            SDL_WINDOWPOS_UNDEFINED_DISPLAY(d), p.width, p.height, flags);
    
    #if OGRE_PLATFORM != OGRE_PLATFORM_EMSCRIPTEN
        SDL_SysWMinfo wmInfo;
        SDL_VERSION(&wmInfo.version);
        SDL_GetWindowWMInfo(ret.native, &wmInfo);
    #endif
    
        // ...
    
        ret.render = mRoot->createRenderWindow(p);
        mWindows.push_back(ret);
        return ret;
    }
    

    通过SDL2创建了一个窗口,然后创建了一个RenderWindow,RenderWindow 包含了一个SwapChain。(D3D11)

    Root是ogre的入口,Application 属于 Component,那么,它并非核心部分,只要能获取其他的窗口句柄,它就应该可以Attach到任意一个窗口上。

    现在归纳一下,SampleBrowser 继承自 FrameListener, InputListener, TrayListener。它就拥有了UI,输入的功能。创建了系统窗口,创建了渲染窗口,接下来就是创建UI了。

    按照之前的获得的信息,创建UI应该在重载的 setup 函数里, 直接去瞄一眼。

    直接在 SampleBrowser::setup里来一个断点调试。F10。

    ApplicationContext::setup();
    

    发现当运行 ApplicationContext::setup() 时, UI 已经在运行了。已知ogre还没有运行到 Frame事件,不会发生更新事件。那么,UI与ogre不是同一个流程。UI的渲染也不是用的ogre渲染系统?

    带着这个疑问,一步一步的调试,发现SampleBrowser重载了 loadResources在里面加载一些资源, 加载资源的时候,会通过 TrayManager::Update 调用到 RenderWindow::Updata,实现刷新画面。

    通过这个现象,猜测可以在任何时候去更新应用的画面。如果UI与Frame同一帧都调用了RenderWindow::Update,怎么防止呢?暂时留着疑问。

    回到 setup,继续

    Sample* startupSample = loadSamples();
    

    从配置文件加载例子

    Ogre::MaterialPtr thumbMat = Ogre::MaterialManager::getSingleton().create("SdkTrays/SampleThumbnail", "Essential");
    thumbMat->setLightingEnabled(false);
    thumbMat->setDepthCheckEnabled(false);
    thumbMat->getTechnique(0)->getPass(0)->createTextureUnitState();
    

    创建缩略图材质

    setupWidgets();
    

    加载UI

    if (startupSample && mFirstRun){
        runSample(startupSample);
    }
    

    运行初始场景

    然后,就是点击UI,选择运行场景了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值