摘要
在这个简短的教程中我们将介绍如何转换多场景管理器。 你可以在here中找到该教程的源码。当你学习本教程的时候,你应该逐步得添加代码到你自己创建的工程中并且观看执行结果。
先决条件
在你选定的IDE中创建一个cpp文件,然后添加如下代码:
#include "ExampleApplication.h" #define CAMERA_NAME "SceneCamera" void setupViewport(RenderWindow *win, SceneManager *curr) { } void dualViewport(RenderWindow *win, SceneManager *primary, SceneManager *secondary) { } class SMTutorialListener : public ExampleFrameListener, public OIS::KeyListener { public: SMTutorialListener(RenderWindow* win, SceneManager *primary, SceneManager *secondary) : ExampleFrameListener(win, primary->getCamera(CAMERA_NAME), true, false), mPrimary(primary), mSecondary(secondary), mDual(false), mContinue(true) { mKeyboard->setEventCallback(this); } bool frameStarted(const FrameEvent& evt) { mKeyboard->capture(); return mContinue; } bool keyPressed(const OIS::KeyEvent &arg) { switch (arg.key) { case OIS::KC_ESCAPE: mContinue = false; break; default: break; } return true; } bool keyReleased(const OIS::KeyEvent &) {return true;} private: SceneManager *mPrimary, *mSecondary; bool mDual, mContinue; static void swap(SceneManager *&first, SceneManager *&second) { SceneManager *tmp = first; first = second; second = tmp; } }; class SMTutorialApplication : public ExampleApplication { public: SMTutorialApplication() { } ~SMTutorialApplication() { } protected: SceneManager *mPrimary, *mSecondary; void chooseSceneManager(void) { } void createCamera() { } void createViewports() { } void createScene(void) { } void createFrameListener(void) { mFrameListener = new SMTutorialListener(mWindow, mPrimary, mSecondary); mFrameListener->showDebugOverlay(true); mRoot->addFrameListener(mFrameListener); } }; #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #include "windows.h" INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT) #else int main(int argc, char **argv) #endif { // Create application object SMTutorialApplication app; try { app.go(); } catch(Exception& e) { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 MessageBoxA(NULL, e.getFullDescription().c_str(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL); #else fprintf(stderr, "An exception has occurred: %s/n", e.getFullDescription().c_str()); #endif } return 0; }
在你继续之前,请保证你可以成功编译这段代码。但是不要在这里就执行该程序。
建立工程
创建场景管理器
在前面的教程我们已经学习了场景管理器, 因此我们就不在对此功能进行详细的说明.我们仅仅只是交换我们所创造的场景。找到 chooseSceneManager ()并将以下代码添加到里面:
mPrimary = mRoot->createSceneManager(ST_GENERIC, "primary"); mSecondary = mRoot->createSceneManager(ST_GENERIC, "secondary");
创建摄像机
接下来我们需要为每一个场景创建一个摄像机,和先前的教程不同的是我们要创建两个名字相同的摄像机。找出createCamera()并将以下代码添加到里面:
mPrimary->createCamera(CAMERA_NAME); mSecondary->createCamera(CAMERA_NAME);
Creating the Viewports
在这个工程中创建视口会和我们先前的教程有些不一样。当你创建视口时,你必须做以下两件事情: 自己建立一个视口和为你使用的摄像机设置纵横比。首先,将以下代码添加到 createViewports()
setupViewport(mWindow, mPrimary);
将以下代码添加到 setupViewport()
win->removeAllViewports(); Camera *cam = curr->getCamera(CAMERA_NAME); Viewport *vp = win->addViewport(cam); vp->setBackgroundColour(ColourValue(0,0,0)); cam->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
创建场景
最后,我们需要为每个场景管理器创建一个场景, 我们不会增加一些复杂的东西, 我们交换两个场景只需要一点点改动,将下面的代码添加到createScene ():
// Setup the TerrainSceneManager mPrimary->setSkyBox(true, "Examples/SpaceSkyBox"); // Setup the Generic SceneManager mSecondary->setSkyDome(true, "Examples/CloudySky", 5, 8);
在继续之前你要保证你的程序能够正确的编译通过. 你可以在现在编译你的程序但是在程序中除了退出没有其他的功能了!
添加功能
添加功能
在做第一件的功能,我们希望添加到该程序使其允许用户使两个SceneManagers()并排侧。当V键被按下时,我们将视口切换的双模式。这是简单的基本计划。要关闭双视口模式,我们只需调用setupViewport(我们在上一节创建的主要场景管理器)重新创建单一模式的视口。当我们想打开它,我们将调用一个新的函数调用dualViewport。我们将继续对视口的状态变量与mDual轨道。添加以下代码到keyPressed():
case OIS::KC_V: mDual = !mDual; if (mDual) dualViewport(mWindow, mPrimary, mSecondary); else setupViewport(mWindow, mPrimary); break;
在我们现在所处的基础上已经用适当的方式交换了mDual变量和函数调用,我们将确定dualViewport()实际上包含的代码,以显示在一次两个视口。
为了显示并排两个SceneManagers,我们基本上做同样的事情,我们已在setupViewport函数完成。唯一的区别是,我们将创建两个视口,和SceneManagers里的相机之一。下面的代码添加到dualViewport():
win->removeAllViewports(); Viewport *vp = 0; Camera *cam = primary->getCamera(CAMERA_NAME); vp = win->addViewport(cam, 0, 0, 0, 0.5, 1); vp->setBackgroundColour(ColourValue(0,0,0)); cam->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight())); cam = secondary->getCamera(CAMERA_NAME); vp = win->addViewport(cam, 1, 0.5, 0, 0.5, 1); vp->setBackgroundColour(ColourValue(0,0,0)); cam->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
所有这一切都应该很熟悉,除了我们已经添加到addViewport函数调用额外的参数。第一个参数这个函数仍然是我们所使用的相机。第二个参数是视口Z顺序(相当于深度缓冲)。Z值大的会显示在Z值小的前面。请注意,你不能有相同的Z顺序两个视口,即使他们不重叠。接下来的两个参数是视口,左侧和顶部位置,必须介于0和1。最后两个参数是宽度和作为屏幕比例的视口的高度(同样,他们必须在0和1)。因此,在这种情况下,我们创建第一个视口将在位置(0,0),将在屏幕的一半水平,所有屏幕都是垂直。第二个将在视口位置(0.5,0),并采取了一半的水平空间和垂直空间的。
编译并运行应用程序。按下V你现在可以显示在同一时间两个SceneManagers。
交换场景
在功能上,我们要添加到我们的计划是每当C键被按下要交换SceneManagers。为了做到这一点,我们会先换上mPrimary和mSecondary变量,这样,当setupViewport或dualViewport函数调用,我们永远不必担心场景管理器中的变量。主要场景管理器将始终显示在单一模式,另一个将始终在dualViewport模式的左侧。添加以下代码到keyPressed():
case OIS::KC_C: swap(mPrimary, mSecondary);
最后我们交换变量,我们需要实际执行的变化。所有我们所要做的就是调用适当的视口设置功能,我们是否在不同的单或双模式:
if (mDual) dualViewport(mWindow, mPrimary, mSecondary); else setupViewport(mWindow, mPrimary); break;
就是这样!编译并运行应用程序。现在我们可以换一个C键的SceneManagers,并交换与V键单模和双模
建议
Overlays
我确保你在程序中会发现,当你在双视口模式下运行,调试的模式下的Ogre覆盖显示了双方。你可能会关闭在覆盖在视口的显示。使用视口::setOverlaysEnabled功能打开和关闭它们。我有此相对简单的改变的本教程的全部源代码full source,所以如果你不知如何做到这一点,请查看相关细节和网页。
最后
始终牢记的视口类,虽然没有很多的功能本身,就是对所有食人魔渲染的关键。不要紧,你有多少SceneManagers创建或在每个场景管理器多少相机时,他们都将呈现给窗口,除非您设定每个摄像机你呈现口。也不要忘记清除你不使用的之前创造的视口!