OGRE教程六代码注释

View Code
  1 /* 使用OGRE默认的资源文件语法分析器得到所有的资源 */
  2 mResourceCfg = "plugins_d.cfg";
  3 Ogre::ConfigFile cf;
  4 cf.load(mResourceCfg);
  5 
  6 Ogre::ConfigFile::SectionInterator seci;
  7 seci = cf.getSectionInterator();
  8 Ogre::ConfigFile::SettingsMultiMap *settings;
  9 Ogre::ConfigFile::SettingsMultiMap::Interator *i;
 10 Ogre::String secName, typeName, archName;
 11 while(seci.hasMoreElement())
 12 {
 13  secName = seci.peekNextKey();
 14  settings = seci.getNext();
 15  for(i=settings->begin(); i != settings->end(); ++i)
 16  {
 17   /* 隐藏了访问资源的细节,不论是文件夹还是ZIP文件,都是透明的 */
 18   typeName = i->first;
 19   archName = i->second;
 20   /* 现在OGRE核心之一资源管理器,就能够直接取得需要的资源 */
 21   Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName,typeName,secName);
 22  }
 23 }
 24 
 25 
 26 /* 你如果不想在你的程序运行前出现配置对话框,可以用Root方法直接写入配置文件 */
 27 Ogre::RenderWindow *mWindow;
 28 /* 这里有个细节问题,即或运算先判断前一个是否成立,如果成立后面一个不会继续判断 */
 29 if(!(mRoot->restoreConfig() || mRoot->showConfigDialog()))
 30 {
 31  return false;
 32 }
 33 /* 你也可以用WIN32API自己创建一个用于渲染的窗口 */
 34 mWindow = mRoot->initialise(true, "Game Render Window");
 35 
 36 /* 一个游戏需要大量的资源文件,可是在某个时刻却只需要其中的一部分;前一部分已经做完,后部分马上完成;
 37  * 不过在此之前,需要设置MipMap的等级,参考笔记中MipMap资料
 38  */
 39 Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
 40 Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
 41 
 42 /* 现在,完成了第一阶段-准备阶段,现在进入启动阶段-创建场景:
 43  * 1. 创建场景管理器
 44  * 2. 创建相机
 45  * 3. 创建观察点
 46  */
 47 Ogre::SceneManager *mSceneMgr;
 48 mSceneMgr = mRoot->createSceneManager("DefaultSceneManager");
 49 Ogre::Camera *mCamera;
 50 mCamera = mSceneMgr->createCamera("DefaultCamera");
 51 mCamera->setPosition(Ogre::Vector3(0,0,80));
 52 mCamera->lookAt(Ogre::Vector3(0,0,-300)); // why -300 ,not 0
 53 mCamera->setNearClipDistance(5);   // 如果相机与物体距离小于5个距离单元,就只能看到物体内部了。
 54 Ogre::Viewport *mViewport;
 55 /* 这里猜测一下设计上的思路:
 56  * 相机、灯光等都被看做特殊的实体,所以应该由资源管理器管理;
 57  * 而观察点并不是一个实体,比如照相的时候别人让你站在某个位置照相,那个位置是属于空间中的点;
 58  * 在这里那个空间就是渲染窗口,所以观察点应该由渲染窗口添加和管理;
 59  * 正是因为将相机也当做实体资源,而资源在OGRE中使用非常灵活,你可以多创建几个相机,摆放好位置,
 60  * 当你想用哪个相机时直接指定那个相机的位置是观察点即可;
 61  * 进一步思考:
 62  * 如果我想将一个渲染窗口分开在不同位置分别观察某个场景,那么实现上应该再创建一个观察点,然后
 63  * 每个观察点单独指定相机。
 64  */
 65 mViewport = mWindow->addViewport(mCamera);
 66 /* 疑问:
 67  * 为什么需要设置观察点的背景颜色呢?难道不是所有的颜色都是由灯光指定?
 68  * 背景颜色的指定是不是相当于指定白天黑夜黄昏?
 69  */
 70 mViewport->setBackgroundColor(Ogre::ColourValue(0,0,0));
 71 /* 疑问:
 72  * 设置相机的纵横比,如果参数偏大,会是什么效果?
 73  * 偏小呢?
 74  */
 75 mCamera->setAspectRatio(Ogre::Real(mViewport->getActualWidth()) / Ogre::Real(mViewport->getActualHeight()));
 76 
 77 /* 现在,启动工作也完成了,只需要载入实体就可以看到丰富的场景效果了 */
 78 /* 因为已经初始化过资源文件了,我们只需要直接指定资源名称就可以使用了 */
 79 Ogre::Entity *ogreHead;
 80 ogreHead = mSceneManager->createEntity("Head", "ogrehead.mesh");
 81 Ogre::SceneNode *headNode;
 82 /* OGRE中实体的名称都必须是惟一的,你可以通过两种方式访问到这些实体:
 83  * 1. 实体句柄,其实是一个指针,比如headNode
 84  * 2. 实体名称,比如headNode指向的场景节点的名称也是headNode
 85  */
 86 headNode = mSceneManager->getRootSeneNode()->createChildSceneNode("headNode");
 87 headNode->setPosition(Ogre::Vector3(0,0,0));
 88 headNode->attachObject(ogreHead);
 89 /* 疑问:
 90  * AmbientLight是环境光,Viewport背景光又是什么呢?
 91  */
 92 mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5,0.5,0.5));
 93 Ogre::Light *light;
 94 light = mSceneMgr->createLight("MainLight");
 95 light->setPosition(Ogre::Vector3(20,100, 50));
 96 
 97 /* 你现在可以得到这个场景的效果图了,不过却是一闪而过的;我希望计算机保持这个场景,
 98  * 并且当我与之交互时,能够改变这个场景中的某个部分;那么你就需要一个循环等待的过程;
 99  * 这个过程在OGRE中叫做渲染循环:
100  * OGRE提供了多种方式让你根据每个循环的特点选取其中一个,最简单的是:
101  * Ogre::Root::RenderOneFrame()
102  * 下面这段代码实现的功能是,一直等待用户关闭窗口,或者渲染一帧画面的时候出错了。
103  */
104 while(true)
105 {
106  Ogre::WindowEventUtilities::messagePump();
107  if(mWindow->isClosed())
108  {
109   return false;
110  }
111  
112  if(!mRoot->RenderOneFrame())
113  {
114   return false;
115  }
116 }
117 
118 /* OIS(Object Oriented Input System )是OGRE推荐使用的用户输入插件;
119  * 如果在进入渲染循环之前设置了OIS,那么我们的鼠标和键盘就能够在场景中得到响应;
120  * 这相当于为OGRE添加了一个中断系统
121  */
122 Ogre::LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");
123 OIS::ParamList pl;
124 size_t WindowHnd = 0;
125 std::ostringstream windowHndStr;
126 
127 mWindow->getCustomAttribute("WINDOW", &windowHnd);
128 windowHndStr << windowHnd;
129 pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
130 
131 mInputManager = OIS::InputManager::createInputSystem(pl);
132 
133 mKeyboard = static_cast<OIS::Keyboard *>(mInputManager->createInputObject(OIS::OISKeyboard, false));
134 mMouse   = static_cast<OIS::Keyboard *>(mInputManager->createInputObject(OIS::OISKeyboard, false));
135 
136 /* 我们不仅要让渲染循环能够响应键盘上对场景的操作,还要在将渲染窗口关闭的时候同时停止OIS模块的运行,
137  * 之所以这么做是因为OIS是独立于OGRE的单独模块,写好后,在主程序中将其注册为窗口监听函数。
138  */
139 void Game::windowClosed(Ogre::RenderWindow *rw)
140 {
141  if(rw == mWindow)
142  {
143   if(mInputManager)
144   {
145    mInputManager->destroyInputObject(mKeyboard);
146    mInputManager->destroyInputObject(mMouse);
147    
148    OIS::InputManager::destroyInputSystem(mInputManager);
149    mInputManager = 0;
150   }
151  }
152 }
153 
154 Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);
155 
156 /* 有了OIS作为内嵌的中断系统,我们可以编写帧监听函数,这些函数实际上相当于中断处理程序 
157  * 首先要在Game类的保护区申明如下定义:
158  * virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);
159  * 在保护区表明该功能不能被继承,然而为何在保护区?
160  */
161 bool Game::frameRenderingQueued(const Ogre::FrameEvent &evt)
162 {
163  if(mWindow->isClosed())
164  {
165   return false;
166  }
167  mKeyboard->capture();
168  mMouse->capture();
169  
170  if(mKeyboard->isKeyDown(OIS::KC_ESCAPE))
171  {
172   return false;
173  }
174  
175  return true;
176 }
177 /* 中断程序写好后,需要注册才能使用 */
178 mRoot->addFrameListener(this);
179 mRoot->startRendering();
180 
181  
182  

 

posted @ 2012-05-13 12:21  jinfengswust  阅读(289)  评论(0编辑  收藏  举报