第一次发送超过字数了,被迫剪成两篇!

上一篇我们介绍了如何搭建开发环境,并创建了一个空白的窗口程序。
这里我们主要是实现在程序中装载一个简单的模型并显示出来。
首先看一下效果吧,(模型就是ogre例子中的robot.mesh),如下:

例子很简单,代码页不多,就4行。我们还是一步一步来分析吧。
首先我们上一个项目中的OgreDemo1类继承自ExampleApplication类,我们之所以什么都没

有做就能创建一个窗口,就是因为ExampleApplication为我们实现了。
首先我们打开ExampleApplication类,可以看到包含了如下几个成员变量(加入了少许注释)

  1. //ogre的程序"根"任何ogre程序都会有改对象     
  2. Root *mRoot;     
  3. //摄像机镜头     
  4. Camera* mCamera;     
  5. //场景管理器     
  6. SceneManager* mSceneMgr;     
  7. //对于每一帧进行处理的类     
  8. ExampleFrameListener* mFrameListener;     
  9. //渲染窗口     
  10. RenderWindow* mWindow;     
  11. //资源文件的路径字符串     
  12. Ogre::String mResourcePath;  

这里的ExampleFrameListener类,如果你暂时还不清楚是做什么的,不要紧,后面我们慢慢介绍。
知道了这些成员变量,我们在返回OgreDemo1.c文件中看看入口函数WinMain中是如何书写的呢
?很简单就一句话:

  1. app.go(); 

先将源代码贴出来,加了详细注意:
ExampleApplication.h

  1. #ifndef __ExampleApplication_H__     
  2. #define __ExampleApplication_H__     
  3.     
  4. #include "Ogre.h"     
  5. #include "OgreConfigFile.h"     
  6. #include "ExampleFrameListener.h"     
  7.     
  8. #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE     
  9. #include <CoreFoundation/CoreFoundation.h>     
  10.     
  11. std::string macBundlePath()     
  12. {     
  13.     char path[1024];     
  14.     CFBundleRef mainBundle = CFBundleGetMainBundle();     
  15.     assert(mainBundle);     
  16.     
  17.     CFURLRef mainBundleURL = CFBundleCopyBundleURL(mainBundle);     
  18.     assert(mainBundleURL);     
  19.     
  20.     CFStringRef cfStringRef = CFURLCopyFileSystemPath( mainBundleURL, kCFURLPOSIXPathStyle);     
  21.     assert(cfStringRef);     
  22.     
  23.     CFStringGetCString(cfStringRef, path, 1024, kCFStringEncodingASCII);     
  24.     
  25.     CFRelease(mainBundleURL);     
  26.     CFRelease(cfStringRef);     
  27.     
  28.     return std::string(path);     
  29. }     
  30. #endif     
  31.     
  32. using namespace Ogre;     
  33.     
  34. /** Base class which manages the standard startup of an Ogre application.    
  35.     Designed to be subclassed for specific examples if required.    
  36. */    
  37. class ExampleApplication     
  38. {     
  39. public:     
  40.     ExampleApplication()     
  41.     {     
  42.         mFrameListener = 0;     
  43.         mRoot = 0;     
  44. #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE     
  45.         mResourcePath = macBundlePath() + "/Contents/Resources/";     
  46. #else     
  47.         mResourcePath = "";     
  48. #endif     
  49.     }     
  50.     /// Standard destructor     
  51.     virtual ~ExampleApplication()     
  52.     {     
  53.         if (mFrameListener)     
  54.             delete mFrameListener;     
  55.         if (mRoot)     
  56.             OGRE_DELETE mRoot;     
  57.     }     
  58.     
  59.     /// 程序的入口     
  60.     virtual void go(void)     
  61.     {     
  62.         //进行初始化工作     
  63.         if (!setup())     
  64.             return;     
  65.         //开始渲染     
  66.         mRoot->startRendering();     
  67.         // 清理屏幕     
  68.         destroyScene();     
  69.     }     
  70.     
  71. protected:     
  72.     //ogre的程序"根"任何ogre程序都会有改对象     
  73.     Root *mRoot;     
  74.     //摄像机镜头     
  75.     Camera* mCamera;     
  76.     //场景管理器     
  77.     SceneManager* mSceneMgr;     
  78.     //对于每一帧进行处理的类     
  79.     ExampleFrameListener* mFrameListener;     
  80.     //渲染窗口     
  81.     RenderWindow* mWindow;     
  82.     //资源文件的路径字符串     
  83.     Ogre::String mResourcePath;     
  84.     //初始化应用程序     
  85.     virtual bool setup(void)     
  86.     {     
  87.         String pluginsPath;     
  88. #ifndef OGRE_STATIC_LIB     
  89.         pluginsPath = mResourcePath + "plugins.cfg";     
  90. #endif     
  91.         //构建Root对象     
  92.         mRoot = OGRE_NEW Root(pluginsPath,      
  93.             mResourcePath + "ogre.cfg", mResourcePath + "Ogre.log");     
  94.         //配置资源文件相关     
  95.         setupResources();     
  96.         //配置,主要用于初始化渲染窗口     
  97.         bool carryOn = configure();     
  98.         if (!carryOn) return false;     
  99.         //创建场景管理器     
  100.         chooseSceneManager();     
  101.         //创建摄像机     
  102.         createCamera();     
  103.         //创建视口     
  104.         createViewports();     
  105.              
  106.         TextureManager::getSingleton().setDefaultNumMipmaps(5);     
  107.         //创建资源监听     
  108.         createResourceListener();     
  109.         //床在资源     
  110.         loadResources();     
  111.         //创建屏幕,必须重写,也就是我们OgreDemo1类中(我们现实模型需要实现的)     
  112.         createScene();     
  113.         //创建帧监听     
  114.         createFrameListener();     
  115.         return true;     
  116.     }     
  117.     /** 是否配置完成,完成则初始化系统 */    
  118.     virtual bool configure(void)     
  119.     {     
  120.         //判断是否进入(即运行过了配置窗口,进入demo窗口)     
  121.         if(mRoot->showConfigDialog())     
  122.         {     
  123.             //初始化系统,得到一个渲染窗口对象     
  124.             mWindow = mRoot->initialise(true);     
  125.             return true;     
  126.         }     
  127.         else    
  128.         {     
  129.             return false;     
  130.         }     
  131.     }     
  132.     
  133.     virtual void chooseSceneManager(void)     
  134.     {     
  135.         // 创建一个场景管理器(场景类型,窗口标题)     
  136.         mSceneMgr = mRoot->createSceneManager(ST_GENERIC, "ExampleSMInstance");     
  137.     }     
  138.     virtual void createCamera(void)     
  139.     {     
  140.         // 创建一个摄像机     
  141.         mCamera = mSceneMgr->createCamera("PlayerCam");     
  142.     
  143.         // 设置摄像机的位置     
  144.         mCamera->setPosition(Vector3(0,0,500));     
  145.         // 设置观察点     
  146.         mCamera->lookAt(Vector3(0,0,-300));     
  147.         // 设置最近裁剪距离,如果超出则不显示     
  148.         mCamera->setNearClipDistance(5);     
  149.         //同样还有设置最远裁剪距离     
  150.         //mCamera->setFarClipDistance(1000);     
  151.     }     
  152.     //创建帧监听     
  153.     virtual void createFrameListener(void)     
  154.     {     
  155.         //实例化帧监听,(渲染窗口,摄像机)     
  156.         mFrameListener= new ExampleFrameListener(mWindow, mCamera);     
  157.         //设置是否显示调试信息(比如:fps...)     
  158.         mFrameListener->showDebugOverlay(true);     
  159.         //添加帧监听到root中     
  160.         mRoot->addFrameListener(mFrameListener);     
  161.     }     
  162.     //创建屏幕     
  163.     virtual void createScene(void) = 0;      
  164.     //清屏     
  165.     virtual void destroyScene(void){}     
  166.     /* 创建视口并初始化 */    
  167.     virtual void createViewports(void)     
  168.     {     
  169.         // 创建一个“视口”     
  170.         Viewport* vp = mWindow->addViewport(mCamera);     
  171.         //设置背景颜色     
  172.         vp->setBackgroundColour(ColourValue(0,0,0));     
  173.     
  174.         //设置屏幕的长宽比(视口的宽度和高度比,目前的宽屏电脑)     
  175.         mCamera->setAspectRatio(Real(vp->getActualWidth()) / Real(vp->getActualHeight()));     
  176.     }     
  177.     
  178.     /// 初始化资源,比如:模型、贴图等资源     
  179.     virtual void setupResources(void)     
  180.     {     
  181.         ConfigFile cf;     
  182.         //读取配置文件     
  183.         cf.load(mResourcePath + "resources.cfg");     
  184.         ConfigFile::SectionIterator seci = cf.getSectionIterator();     
  185.         String secName, typeName, archName;     
  186.         while (seci.hasMoreElements())     
  187.         {     
  188.             secName = seci.peekNextKey();     
  189.             ConfigFile::SettingsMultiMap *settings = seci.getNext();     
  190.             ConfigFile::SettingsMultiMap::iterator i;     
  191.             for (i = settings->begin(); i != settings->end(); ++i)     
  192.             {     
  193.                 //取得并添加资源文件     
  194.                 typeName = i->first;     
  195.                 archName = i->second;     
  196. #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE     
  197.                 ResourceGroupManager::getSingleton().addResourceLocation(     
  198.                     String(macBundlePath() + "/" + archName), typeName, secName);     
  199. #else     
  200.                 ResourceGroupManager::getSingleton().addResourceLocation(     
  201.                     archName, typeName, secName);     
  202. #endif     
  203.             }     
  204.         }     
  205.     }     
  206.     
  207.     //创建资源监听,比如(正在装载资源,请稍等界面)     
  208.     virtual void createResourceListener(void)     
  209.     {     
  210.     }     
  211.     
  212.     //装载资源     
  213.     virtual void loadResources(void)     
  214.     {     
  215.         ResourceGroupManager::getSingleton().initialiseAllResourceGroups();     
  216.     }     
  217. };     
  218.     
  219.     
  220. #endif  

ExampleFrameListener.h

  1. #ifndef __ExampleFrameListener_H__     
  2. #define __ExampleFrameListener_H__     
  3.     
  4. #include "Ogre.h"     
  5. #include "OgreStringConverter.h"     
  6. #include "OgreException.h"     
  7. #define OIS_DYNAMIC_LIB     
  8. #include <OIS/OIS.h>     
  9.     
  10. using namespace Ogre;     
  11.     
  12. class ExampleFrameListener: public FrameListener, public WindowEventListener     
  13. {     
  14. protected:     
  15.     virtual void updateStats(void)     
  16.     {     
  17.         static String currFps = "Current FPS: ";     
  18.         static String avgFps = "Average FPS: ";     
  19.         static String bestFps = "Best FPS: ";     
  20.         static String worstFps = "Worst FPS: ";     
  21.         static String tris = "Triangle Count: ";     
  22.         static String batches = "Batch Count: ";     
  23.     
  24.         // 需要更新debug信息时更新     
  25.         try {     
  26.             OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps");     
  27.             OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps");     
  28.             OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps");     
  29.             OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps");     
  30.     
  31.             const RenderTarget::FrameStats& stats = mWindow->getStatistics();     
  32.             guiAvg->setCaption(avgFps + StringConverter::toString(stats.avgFPS));     
  33.             guiCurr->setCaption(currFps + StringConverter::toString(stats.lastFPS));     
  34.             guiBest->setCaption(bestFps + StringConverter::toString(stats.bestFPS)     
  35.                 +" "+StringConverter::toString(stats.bestFrameTime)+" ms");     
  36.             guiWorst->setCaption(worstFps + StringConverter::toString(stats.worstFPS)     
  37.                 +" "+StringConverter::toString(stats.worstFrameTime)+" ms");     
  38.     
  39.             OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris");     
  40.             guiTris->setCaption(tris + StringConverter::toString(stats.triangleCount));     
  41.     
  42.             OverlayElement* guiBatches = OverlayManager::getSingleton().getOverlayElement("Core/NumBatches");     
  43.             guiBatches->setCaption(batches + StringConverter::toString(stats.batchCount));     
  44.     
  45.             OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText");     
  46.             guiDbg->setCaption(mDebugText);     
  47.         }     
  48.         catch(...) { /* ignore */ }     
  49.     }     
  50.     
  51. public:     
  52.     // 构造函数,初始化成员变量     
  53.     ExampleFrameListener(RenderWindow* win, Camera* cam, bool bufferedKeys = falsebool bufferedMouse = false,     
  54.                  bool bufferedJoy = false ) :     
  55.         mCamera(cam), mTranslateVector(Vector3::ZERO), mCurrentSpeed(0), mWindow(win), mStatsOn(true), mNumScreenShots(0),     
  56.         mMoveScale(0.0f), mRotScale(0.0f), mTimeUntilNextToggle(0), mFiltering(TFO_BILINEAR),     
  57.         mAniso(1), mSceneDetailIndex(0), mMoveSpeed(100), mRotateSpeed(36), mDebugOverlay(0),     
  58.         mInputManager(0), mMouse(0), mKeyboard(0), mJoy(0)     
  59.     {     
  60.         //得到debug视图     
  61.         mDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");     
  62.         //日志管理器     
  63.         LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");     
  64.         OIS::ParamList pl;     
  65.         size_t windowHnd = 0;     
  66.         std::ostringstream windowHndStr;     
  67.         //取得自定义的属性     
  68.         win->getCustomAttribute("WINDOW", &windowHnd);     
  69.         windowHndStr << windowHnd;     
  70.         pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));     
  71.         //创建输入管理器     
  72.         mInputManager = OIS::InputManager::createInputSystem( pl );     
  73.     
  74.         //创建输入设备、鼠标、键盘、摇杆     
  75.         mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, bufferedKeys ));     
  76.         mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, bufferedMouse ));     
  77.         try {     
  78.             mJoy = static_cast<OIS::JoyStick*>(mInputManager->createInputObject( OIS::OISJoyStick, bufferedJoy ));     
  79.         }     
  80.         catch(...) {     
  81.             mJoy = 0;     
  82.         }     
  83.     
  84.         //根据窗口的大小来设置鼠标的初始裁剪区域     
  85.         windowResized(mWindow);     
  86.         //显示debug信息     
  87.         showDebugOverlay(true);     
  88.     
  89.         //注册一个windows窗口事件监听     
  90.         WindowEventUtilities::addWindowEventListener(mWindow, this);     
  91.     }     
  92.     
  93.     //调整鼠标裁剪区域     
  94.     virtual void windowResized(RenderWindow* rw)     
  95.     {     
  96.         unsigned int width, height, depth;     
  97.         int left, top;     
  98.         //取得窗口矩阵     
  99.         rw->getMetrics(width, height, depth, left, top);     
  100.         //得到鼠标     
  101.         const OIS::MouseState &ms = mMouse->getMouseState();     
  102.         ms.width = width;     
  103.         ms.height = height;     
  104.     }     
  105.     
  106.     //关闭窗口之前进行的处理     
  107.     virtual void windowClosed(RenderWindow* rw)     
  108.     {     
  109.         //检测是否关闭了我们的渲染窗口     
  110.         if( rw == mWindow )     
  111.         {     
  112.             if( mInputManager )     
  113.             {     
  114.                 //清除输入设备     
  115.                 mInputManager->destroyInputObject( mMouse );     
  116.                 mInputManager->destroyInputObject( mKeyboard );     
  117.                 mInputManager->destroyInputObject( mJoy );     
  118.                 //销毁输入管理器     
  119.                 OIS::InputManager::destroyInputSystem(mInputManager);     
  120.                 mInputManager = 0;     
  121.             }     
  122.         }     
  123.     }     
  124.     
  125.     virtual ~ExampleFrameListener()     
  126.     {     
  127.         //移除所有的窗口事件监听     
  128.         WindowEventUtilities::removeWindowEventListener(mWindow, this);     
  129.         //关闭窗口     
  130.         windowClosed(mWindow);     
  131.     }     
  132.     //按键事件处理     
  133.     virtual bool processUnbufferedKeyInput(const FrameEvent& evt)     
  134.     {     
  135.     
  136.         if(mKeyboard->isKeyDown(OIS::KC_A))     
  137.             mTranslateVector.x = -mMoveScale;   // 向左移动摄像头矩阵     
  138.     
  139.         if(mKeyboard->isKeyDown(OIS::KC_D))     
  140.             mTranslateVector.x = mMoveScale;    // Move camera RIGHT     
  141.     
  142.         if(mKeyboard->isKeyDown(OIS::KC_UP) || mKeyboard->isKeyDown(OIS::KC_W) )     
  143.             mTranslateVector.z = -mMoveScale;   // Move camera forward     
  144.     
  145.         if(mKeyboard->isKeyDown(OIS::KC_DOWN) || mKeyboard->isKeyDown(OIS::KC_S) )     
  146.             mTranslateVector.z = mMoveScale;    // Move camera backward     
  147.     
  148.         if(mKeyboard->isKeyDown(OIS::KC_PGUP))     
  149.             mTranslateVector.y = mMoveScale;    // Move camera up     
  150.     
  151.         if(mKeyboard->isKeyDown(OIS::KC_PGDOWN))     
  152.             mTranslateVector.y = -mMoveScale;   // Move camera down     
  153.     
  154.         if(mKeyboard->isKeyDown(OIS::KC_RIGHT))     
  155.             mCamera->yaw(-mRotScale);     
  156.     
  157.         if(mKeyboard->isKeyDown(OIS::KC_LEFT))     
  158.             mCamera->yaw(mRotScale);     
  159.     
  160.         if( mKeyboard->isKeyDown(OIS::KC_ESCAPE) || mKeyboard->isKeyDown(OIS::KC_Q) )     
  161.             return false;     
  162.     
  163.         if( mKeyboard->isKeyDown(OIS::KC_F) && mTimeUntilNextToggle <= 0 )     
  164.         {     
  165.             mStatsOn = !mStatsOn;     
  166.             showDebugOverlay(mStatsOn);     
  167.             mTimeUntilNextToggle = 1;     
  168.         }     
  169.     
  170.         if( mKeyboard->isKeyDown(OIS::KC_T) && mTimeUntilNextToggle <= 0 )     
  171.         {     
  172.             switch(mFiltering)     
  173.             {     
  174.             case TFO_BILINEAR:     
  175.                 mFiltering = TFO_TRILINEAR;     
  176.                 mAniso = 1;     
  177.                 break;     
  178.             case TFO_TRILINEAR:     
  179.                 mFiltering = TFO_ANISOTROPIC;     
  180.                 mAniso = 8;     
  181.                 break;     
  182.             case TFO_ANISOTROPIC:     
  183.                 mFiltering = TFO_BILINEAR;     
  184.                 mAniso = 1;     
  185.                 break;     
  186.             defaultbreak;     
  187.             }     
  188.             MaterialManager::getSingleton().setDefaultTextureFiltering(mFiltering);     
  189.             MaterialManager::getSingleton().setDefaultAnisotropy(mAniso);     
  190.     
  191.             showDebugOverlay(mStatsOn);     
  192.             mTimeUntilNextToggle = 1;     
  193.         }     
  194.     
  195.         if(mKeyboard->isKeyDown(OIS::KC_SYSRQ) && mTimeUntilNextToggle <= 0)     
  196.         {     
  197.             std::ostringstream ss;     
  198.             ss << "screenshot_" << ++mNumScreenShots << ".png";     
  199.             mWindow->writeContentsToFile(ss.str());     
  200.             mTimeUntilNextToggle = 0.5;     
  201.             mDebugText = "Saved: " + ss.str();     
  202.         }     
  203.     
  204.         if(mKeyboard->isKeyDown(OIS::KC_R) && mTimeUntilNextToggle <=0)     
  205.         {     
  206.             mSceneDetailIndex = (mSceneDetailIndex+1)%3 ;     
  207.             switch(mSceneDetailIndex) {     
  208.                 case 0 : mCamera->setPolygonMode(PM_SOLID); break;//设置多边形的模式     
  209.                 case 1 : mCamera->setPolygonMode(PM_WIREFRAME); break;     
  210.                 case 2 : mCamera->setPolygonMode(PM_POINTS); break;     
  211.             }     
  212.             mTimeUntilNextToggle = 0.5;     
  213.         }     
  214.     
  215.         static bool displayCameraDetails = false;     
  216.         if(mKeyboard->isKeyDown(OIS::KC_P) && mTimeUntilNextToggle <= 0)     
  217.         {     
  218.             displayCameraDetails = !displayCameraDetails;     
  219.             mTimeUntilNextToggle = 0.5;     
  220.             if (!displayCameraDetails)     
  221.                 mDebugText = "";     
  222.         }     
  223.     
  224.         if(displayCameraDetails)     
  225.             mDebugText = "P: " + StringConverter::toString(mCamera->getDerivedPosition()) +     
  226.                          " " + "O: " + StringConverter::toString(mCamera->getDerivedOrientation());     
  227.         return true;     
  228.     }     
  229.     //鼠标事件处理     
  230.     virtual bool processUnbufferedMouseInput(const FrameEvent& evt)     
  231.     {     
  232.     
  233.         // Rotation factors, may not be used if the second mouse button is pressed     
  234.         // 2nd mouse button - slide, otherwise rotate     
  235.         const OIS::MouseState &ms = mMouse->getMouseState();     
  236.         if( ms.buttonDown( OIS::MB_Right ) )     
  237.         {     
  238.             mTranslateVector.x += ms.X.rel * 0.13;     
  239.             mTranslateVector.y -= ms.Y.rel * 0.13;     
  240.         }     
  241.         else    
  242.         {     
  243.             mRotX = Degree(-ms.X.rel * 0.13);     
  244.             mRotY = Degree(-ms.Y.rel * 0.13);     
  245.         }     
  246.     
  247.         return true;     
  248.     }     
  249.     
  250.     //移动摄像头     
  251.     virtual void moveCamera()     
  252.     {     
  253.         //偏移     
  254.         mCamera->yaw(mRotX);     
  255.         //倾斜     
  256.         mCamera->pitch(mRotY);     
  257.         //移动摄像机到指定位置     
  258.         mCamera->moveRelative(mTranslateVector);     
  259.     }     
  260.     //显示debug信息     
  261.     virtual void showDebugOverlay(bool show)     
  262.     {     
  263.         if (mDebugOverlay)     
  264.         {     
  265.             if (show)     
  266.                 mDebugOverlay->show();     
  267.             else    
  268.                 mDebugOverlay->hide();     
  269.         }     
  270.     }     
  271.     
  272.     // 渲染队列     
  273.     bool frameRenderingQueued(const FrameEvent& evt)     
  274.     {     
  275.     
  276.         if(mWindow->isClosed())  return false;     
  277.     
  278.         mSpeedLimit = mMoveScale * evt.timeSinceLastFrame;     
  279.     
  280.         //捕获、更新设备     
  281.         mKeyboard->capture();     
  282.         mMouse->capture();     
  283.         if( mJoy ) mJoy->capture();     
  284.     
  285.         bool buffJ = (mJoy) ? mJoy->buffered() : true;     
  286.     
  287.         Ogre::Vector3 lastMotion = mTranslateVector;     
  288.         if( !mMouse->buffered() || !mKeyboard->buffered() || !buffJ )     
  289.         {     
  290.             // one of the input modes is immediate, so setup what is needed for immediate movement     
  291.             if (mTimeUntilNextToggle >= 0)     
  292.                 mTimeUntilNextToggle -= evt.timeSinceLastFrame;     
  293.     
  294.             // Move about 100 units per second     
  295.             mMoveScale = mMoveSpeed * evt.timeSinceLastFrame;     
  296.             // Take about 10 seconds for full rotation     
  297.             mRotScale = mRotateSpeed * evt.timeSinceLastFrame;     
  298.     
  299.             mRotX = 0;     
  300.             mRotY = 0;     
  301.             mTranslateVector = Ogre::Vector3::ZERO;     
  302.     
  303.         }     
  304.     
  305.         //Check to see which device is not buffered, and handle it     
  306.         if( !mKeyboard->buffered() )     
  307.             if( processUnbufferedKeyInput(evt) == false )     
  308.                 return false;     
  309.         if( !mMouse->buffered() )     
  310.             if( processUnbufferedMouseInput(evt) == false )     
  311.                 return false;     
  312.     
  313.         // ramp up / ramp down speed     
  314.         if (mTranslateVector == Ogre::Vector3::ZERO)     
  315.         {     
  316.             // decay (one third speed)     
  317.             mCurrentSpeed -= evt.timeSinceLastFrame * 0.3;     
  318.             mTranslateVector = lastMotion;     
  319.         }     
  320.         else    
  321.         {     
  322.             // ramp up     
  323.             mCurrentSpeed += evt.timeSinceLastFrame;     
  324.     
  325.         }     
  326.         // Limit motion speed     
  327.         if (mCurrentSpeed > 1.0)     
  328.             mCurrentSpeed = 1.0;     
  329.         if (mCurrentSpeed < 0.0)     
  330.             mCurrentSpeed = 0.0;     
  331.     
  332.         mTranslateVector *= mCurrentSpeed;     
  333.     
  334.     
  335.         if( !mMouse->buffered() || !mKeyboard->buffered() || !buffJ )     
  336.             moveCamera();     
  337.     
  338.         return true;     
  339.     }     
  340.     
  341.     //帧结束,更新状态     
  342.     bool frameEnded(const FrameEvent& evt)     
  343.     {     
  344.         updateStats();     
  345.         return true;     
  346.     }     
  347.     
  348. protected:     
  349.     //指向摄像机的指针     
  350.     Camera* mCamera;     
  351.     //一个3维向量,用于摄像机的位置变换     
  352.     Vector3 mTranslateVector;     
  353.     Real mCurrentSpeed;     
  354.     //指向渲染窗口的指针     
  355.     RenderWindow* mWindow;     
  356.     //是否显示调试信息     
  357.     bool mStatsOn;     
  358.     //debug信息     
  359.     std::string mDebugText;     
  360.     //主要用于截图     
  361.     unsigned int mNumScreenShots;     
  362.     //该demo中,摄像机会旋转     
  363.     float mMoveScale;     
  364.     //速度限制     
  365.     float mSpeedLimit;     
  366.     //同样用于摄像机变换     
  367.     Degree mRotScale;     
  368.     //延时     
  369.     Real mTimeUntilNextToggle ;     
  370.     //鼠标旋转的角度,用于摄像机的更新     
  371.     Radian mRotX, mRotY;     
  372.     //纹理差值的类型,枚举类型     
  373.     TextureFilterOptions mFiltering;     
  374.     int mAniso;     
  375.     int mSceneDetailIndex ;     
  376.     //移动速度     
  377.     Real mMoveSpeed;     
  378.     //旋转速度     
  379.     Degree mRotateSpeed;     
  380.     //debug视图     
  381.     Overlay* mDebugOverlay;     
  382.     
  383.     //一些输入设备(输入设备管理器)     
  384.     OIS::InputManager* mInputManager;     
  385.     //鼠标     
  386.     OIS::Mouse*    mMouse;     
  387.     //键盘     
  388.     OIS::Keyboard* mKeyboard;     
  389.     //摇杆     
  390.     OIS::JoyStick* mJoy;     
  391. };     
  392.     
  393. #endif  

接续(二)