Ogre wizard standard Application…

xiaoxiao2021-02-28  102

                                    转载请注明出处http://blog.sina.com.cn/u/1580340211

         因为最近重拾Ogre,决定重新研究一遍以前不是弄得很懂的例子程序的框架,这个框架不同于ExampleApplication里的框架,主线比较明确,所以理解起来也是比较快的,从go函数入手很快就可以理解Ogre从资源初始化->资源加载->初始化->使用资源创建场景(并增加监听)的一整个过程:

1)  首先可以从应用程序的入口点着手:

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32

    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )

#else

    int main(int argc, char *argv[])

#endif

    {

        // Create application object

        TestCEGUI076 app;

 

        try {

            app.go();

        } catch( Ogre::Exception& e ) {

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32

            MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);

#else

            std::cerr << "An exception has occured: " <<

                e.getFullDescription().c_str() << std::endl;

#endif

        }

 

        return 0;

    }

 

#ifdef __cplusplus

}

#endif

可以看到,在WIN32平台下,Ogre通过try应用程序实例app,进入其入口函数go()中,开始一整个的渲染流程;

2)  于是我们从go()函数开始研究其过程(我们的类是继承于已有的BaseApplication,所以基本的功能在其中已经定义,当然也包括go函数)

void BaseApplication::go(void)

{

#ifdef _DEBUG

    mResourcesCfg = "resources_d.cfg";

    mPluginsCfg = "plugins_d.cfg";

#else

    mResourcesCfg = "resources.cfg";

    mPluginsCfg = "plugins.cfg";

#endif

 

    if (!setup())

        return;

 

    mRoot->startRendering();

 

    // clean up

    destroyScene();

}

 

3)  如上可以看到Ogre中各个功能模块所调用的函数(首先由cfg文件资源路径,然后使用setup函数加载资源,调用根节点的startRedering函数开始渲染,最后destroyscene函数销毁场景),下面分开看这些函数做了一些什么事:

Setup

bool BaseApplication::setup(void)

{

    mRoot = new Ogre::Root(mPluginsCfg);  --------------加载插件初始化Root(注意此处的是plugincfg

 

    setupResources();                      --------------------真正执行资源装载的函数,等会再说

 

    bool carryOn = configure();

    if (!carryOn) return false;            --------------------资源成功加载才继续运行程序

 

    chooseSceneManager();                  -------------------选择渲染器

    createCamera();                        --------------------创建相机

    createViewports();                     ---------------------创建视口

 

    // Set default mipmap level (NB some APIs ignore this)

    Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);----- ---设置默认的mipmap等级

 

    // Create any resource listeners (for loading screens)

    createResourceListener();                           ------------------创建资源监听器(例子中为空,可以自己实现资源的监听)

    // Load resources

    loadResources();                                      ----------------装载资源

 

    // Create the scene

    createScene();                                       ------------------创建场景

 

    createFrameListener();                               ------------------创建帧监听

   

     return true;

};

于是我们就要问那么setupResources做了什么呢?

Setupresources

void BaseApplication::setupResources(void)

{

    // Load resource paths from config file

    Ogre::ConfigFile cf;

    cf.load(mResourcesCfg);资源是通过Resources cfg加载的(这就明确了为什么你要在本地文件夹中包含plugins_d.cfgresources_d.cfg了吧,当然你可以在go函数中就指定路径加载这两个文件,但是这种方法是难以继承的)

 

    // Go through all sections & settings in the file

    Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator(); -----创建迭代器逐个加载资源

 

    Ogre::String secName, typeName, archName;

    while (seci.hasMoreElements())           --------------------循环判断资源类型并加载(从读文件的方式你就可以看出为什么cfg中的资源路径要使用那样的命名方式了吧)

    {

        secName = seci.peekNextKey();

        Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();

        Ogre::ConfigFile::SettingsMultiMap::iterator i;

        for (i = settings->begin(); i != settings->end(); ++i)

        {

            typeName = i->first;

            archName = i->second;

            Ogre::ResourceGroupManager::getSingleton().addResourceLocation(

                archName, typeName, secName);-- -加载资源的三个变量分别是【资源类型】【类型名】【组名称】

        }

    }

}

通过使用setupresources加载了资源后,在setup中我们就可以调用相关的函数来构建基本的环境了(首先要创建场景管理器,因为其他的包括节点和实体都要通过调用其单例来完成):

ChooseSceneManager

void BaseApplication::chooseSceneManager(void)

{

    // Get the SceneManager, in this case a generic one

    mSceneMgr = mRoot->createSceneManager(Ogre::ST_GENERIC);         ------------此处调用的是一般的渲染器,如果场景需要可以调用其余的三个渲染器加速渲染

}

CreateCamera

void BaseApplication::createCamera(void)

{

    // Create the camera

    mCamera = mSceneMgr->createCamera("PlayerCam");

 

    // Position it at 500 in Z direction

    mCamera->setPosition(Ogre::Vector3(0,0,80));

    // Look back along -Z

    mCamera->lookAt(Ogre::Vector3(0,0,-300));

    mCamera->setNearClipDistance(5);

 

    mCameraMan = new OgreBites::SdkCameraMan(mCamera);   // create a default camera controller------创建一个camera的管理器,通过此种方法简化了相机的控制,不过特殊的移动相机要求需要自己在OIS回调函数中实现

}

createViewport

void BaseApplication::createViewports(void)

{

    // Create one viewport, entire window

    Ogre::Viewport* vp = mWindow->addViewport(mCamera);

    vp->setBackgroundColour(Ogre::ColourValue(0,0,0));

 

    // Alter the camera aspect ratio to match the viewport

    mCamera->setAspectRatio( ----------注意不加此步你就杯具了,变化窗口大小会出现图像变形或者空白部分

        Ogre::Real(vp->getActualWidth()) / Ogre::Real(vp->getActualHeight()));

}

setup中创建了相机和视口并且设置mipmap之后就可以完成资源的加载了,主要是通过loadResources()函数完成:

LoadResources

void BaseApplication::loadResources(void)

{

    Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

}

就一个函数初始化所有资源组,没啥好说的额。

然后呢,在setup中还有两个十分重要的函数就是createScene()和createFrameListener了。

creteScene

  virtual void createScene(void) = 0; // Override me!

顾名思义,就是需要你自己去实现的场景构造函数了,它里面已经指明是一个虚函数,如果没有将其覆盖你是确定一定以及肯定的是二了。

CreateFrameListener

void BaseApplication::createFrameListener(void)

{

    Ogre::LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");

    OIS::ParamList pl; -----------------初始化OISLog系统,同时也完成键盘鼠标的回调初始化

    size_t windowHnd = 0;

    std::ostringstream windowHndStr;

 

    mWindow->getCustomAttribute("WINDOW", &windowHnd);

    windowHndStr << windowHnd;

    pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));

 

    mInputManager = OIS::InputManager::createInputSystem( pl );-----------创建基于windows的输入系统这里是很重要的,有了这个部分才能够正确的处理鼠标和键盘事件

 

    mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, true ));

    mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, true ));

 

    mMouse->setEventCallback(this);

    mKeyboard->setEventCallback(this);

 

    //Set initial mouse clipping size

    windowResized(mWindow);

 

    //Register as a Window listener

    Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);

 

    mTrayMgr = new OgreBites::SdkTrayManager("InterfaceName", mWindow, mMouse, this);---因为是Ogre自己的例子wizard所以它选择用自己的一套UI,主要是利用包含在OgreBites中的Trays完成,其实我不是很懂,但是实际用起来应该是要简单一点的,毕竟它下面只用了一个栈就建立了UI

    mTrayMgr->showFrameStats(OgreBites::TL_BOTTOMLEFT);

    mTrayMgr->showLogo(OgreBites::TL_BOTTOMRIGHT);

    mTrayMgr->hideCursor();

 

    // create a params panel for displaying sample details

    Ogre::StringVector items;

    items.push_back("cam.pX");

    items.push_back("cam.pY");

    items.push_back("cam.pZ");

    items.push_back("");

    items.push_back("cam.oW");

    items.push_back("cam.oX");

    items.push_back("cam.oY");

    items.push_back("cam.oZ");

    items.push_back("");

    items.push_back("Filtering");

    items.push_back("Poly Mode");

 

    mDetailsPanel = mTrayMgr->createParamsPanel(OgreBites::TL_NONE, "DetailsPanel", 200, items);

    mDetailsPanel->setParamValue(9, "Bilinear");

    mDetailsPanel->setParamValue(10, "Solid");

    mDetailsPanel->hide();

 

    mRoot->addFrameListener(this); ------------调用函数为本类注册监听

}

4)  好了,setup完成以后就可以开始从根节点调用startRendering()进行渲染了,至于为什么可以循环渲染就是Ogre渲染循环的问题了,留待以后再详细的说明。

5)  DestroyScene也是一个需要注意的问题,虽然例子中没有具体的内容,但是在自己实现的时候需要在此处释放你之前自己load的各种资源(创建的粒子系统,CEGUIdestroy等等)

好了,通过Ogre的标准例子程序,现在已经对于Ogre渲染流程有了初步了解,可以自己慢慢在其中添加各种功能了,这个例子程序充分的体现出了Ogre仅仅是一个实现框架,最大的功能是提供了一个有效组织各种资源和渲染系统的平台,利用其灵活并且日渐完善的平台体系,越来越多的库被添加到其中,形成一个十分强大的3D渲染引擎,因其开源特性,Ogre 的更新是非常快的,所以给学习图形或者是3D渲染和游戏编程的童鞋提供了非常好的学习资料(只是不知为何最近Ogre3D开放资源地带不能上了,是域名到期疑惑天朝一片河蟹不得而知…..)

 

转载请注明原文地址: https://www.6miu.com/read-32188.html

最新回复(0)