Ogre给的教程框架还是很友好的,继承其所给的BaseApplication类,只用重写createScene函数,就可以渲染出mesh模型了。但是为了更好的学习,当然要搞清楚BaseAplication中的每一段代码都做了什么。官方的第Basic Tutorial第6节讲的很清楚。
1.wiki上的tutorial给定建议启动流程
1.create the root object. 创建根对象
2.define the resource that Ogre will use. 定义一个Ogre将要使用的资源文件
3.choose and setup the RenderingSystem. 选择和启动一个渲染器(例如,OpenGL,DirectX)
4.create Rendering Window. 创建一个Ogre渲染的窗口
5.Initialize the resources that you are going to use. 初始化所有要使用的资源
6.create a scene use the resource. 利用资源创建一个场景。
7.set up any thirdparty puligins and library. 设置所有的第三方插件与库
8.create any numbers of frame listeners. 创建任意数量的frameListener
9.start the render loop. 开始渲染循环
当然,wiki上也说了,你可以不按着规矩来,但是1-4一定要乖乖的按着顺序做,7-8可以放在5-6之前,但是这样在resources和secne创建完成之前第三方插件和frameListener是无法获取任何和resource以及scene相关的内容的。
2.具体实现
2.1创建根对象
#ifdef _DEBUG
mPluginsCfg = "plugins_d.cfg";
#else
mPluginsCfg = "plugins.cfg";
#endif
// construct Ogre::Root
mRoot = new Ogre::Root(mPluginsCfg);
return true;
根对象root的构造函数有3个参数,均有默认值:
参数类型:String | 默认值 | 描述 |
pluginFileName | “plugin.cg” | 插件配置文件的名称和路径 |
configFileName | "ogre.cfg" | 生成的ogre配置文件名称和路径 |
logFileName | "Ogre.log" | 生成的log文件名称和路径 |
plugin.cfg是必须事先编写好的,告诉根对象需要加载哪些插件,否则Ogre引擎直接启动失败,并抛出异常,至于plugin.cfg文件,在你编译好的SampleBroswer目下就有,拷贝过来用就行了,至于Ogre的插件系统我也还没有弄清楚,就先不详细说了。
后面两个都是Ogre输出的文件,log好理解,就是日志信息了,出了什么错,什么异常,都会记录在里面,在Linux下其实这些信息都打印在终端里了,至于windows,估计出了问题,就要好好看log了。至于ogre.cfg,是root为你保存的第一次开启引擎时记录的信息,例如:显卡,渲染器类型,全屏,分辨率,垂直同步等等,还记得SampleBroswer第一次开启时,会有一个小Dialog让你配置选项么,但是第二次启动就没有了,就是因为Ogre为你保存了你的配置,不需要你反复的输入,当然如果你希望换个配置,但是在程序内部又没有提供相应的接口,那么直接删掉这个文件即可,再启动时,Ogre会让你重新配置系统信息的。
2.2定义资源文件信息
#ifdef _DEBUG
mResourcesCfg = "resources_d.cfg";
#else
mResourcesCfg = "resources.cfg";
#endif
// set up resources
// Load resource paths from config file
Ogre::ConfigFile cf;
cf.load(mResourcesCfg);
// Go through all sections & settings in the file
Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
Ogre::String secName, typeName, archName;
while (seci.hasMoreElements())
{
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);
}
}
记住,根对象一定是第一个创建的,其后才能加载资源文件,否则将发生错误。
2.3选择一个渲染系统
这个没什么好说的,无非就是OpenGL或者DX,我在Fedora下也没什么选择,直接OpenGL完事。RenderSystem *rs = mRoot->getRenderSystemByName("OpenGL Rendering Subsystem");
mRoot->setRenderSystem(rs);
rs->setConfigOption("Full Screen", "No");
rs->setConfigOption("Video Mode", "1366 x 768 @ 32-bit colour");
另外,选择好了渲染系统后,这里还是继续配置一些相关的信息,例如是否全屏拉,分辨率拉,显卡类型拉很多很多,当然,如果你想把这个选择的权利交给用户,你可以用根对象的showConfigDialog()方法来为你弹出一个配置对话框,十分方便。
// configure
// Show the configuration dialog and initialise the system
if(!(mRoot->restoreConfig() || mRoot->showConfigDialog()))
{
return false;
}
这里有个restoreConfig()混在里面,是为了实现上述说过的,第一次配置完后,Ogre会为你生成一个ogre.cfg文件保存你上次的配置,这样就不用每次开启程序时都要设置一遍了。
2.4创建渲染窗口
第三步之前的编译运行后,如果你观察啊终端输出或者log文件,会发现Ogre什么都没有做就退出了,其实并不是什么都没有做,只是没有找到一个可供它渲染的窗口,于是它自动退出了,但是前面所提到的加载插件,加载资源,Ogre可是一个也没落下。用以下方法就可以简单的创建一个渲染窗口了:Ogre::RenderWindow* mWindow;
mWindow = mRoot->initialise(true, "Render Window");
当然,如果你想要把Ogre嵌入你的win32窗口,或者其他的什么GUI窗口,Linux下GUi如Qt等等,wiki也给出了答案:
mRoot->initialise(false);
HWND hWnd = 0; // Get the hWnd of the application!
NameValuePairList misc;
misc["externalWindowHandle"] = StringConverter::toString((int)hWnd);
RenderWindow *win = mRoot->createRenderWindow("Main RenderWindow", 800, 600, false, &misc);
注意到,这与简单的初始化一个窗口唯一的区别就是,在调用Ogre::RenderWindow的initialise方法时,没有直接使用true参数,而是在后面通过HWND获取你想要嵌入的窗体的句柄,至于这个句柄怎么获得,那就取决于你用的GUI类型了,之后根对象的createRenderWindow()方法可以帮你将Ogre的渲染窗口指定为你所提供的其它GUI如win32已经建立的窗体,至于这些API具体怎么用大家去看官方手册吧。
2.5加载资源
2.6创建场景信息:包括entity,node,light等等
// Set default mipmap level (note: some APIs ignore this)
Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
// initialise all resource groups
Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
至于第六步也就是创建场景信息,我就不多说了,内容太多,可以自己去wiki上学习,讲的很清楚。
2.7加载第三方插件
2.8创建任意数量的帧监听器(FrameListener)
2.9进入渲染循环
Ogre通过调用Ogre::Root::startRendering()就可以进入渲染循环了,当然,Ogre的渲染循环具体是那样的呢,wiki上也解释的很清楚,可以理解如为如下代码:void Root::startRendering(void)
{
assert(mActiveRenderer != 0);
mActiveRenderer->_initRenderTargets();
// Clear event times
clearEventTimes();
// Infinite loop, until broken out of by frame listeners
// or break out by calling queueEndRendering()
mQueuedEnd = false;
while( !mQueuedEnd )
{
//Pump messages in all registered RenderWindow windows
WindowEventUtilities::messagePump();
if (!renderOneFrame())
break;
}
}
这里其实循环最关键的就是while中的renderOneFrame这个函数的,这个函数可以这样理解:
bool Root::renderOneFrame(void)
{
if(!_fireFrameStarted())
return false;
if(!_updateAllRenderTargets())
return false;
return _fireFrameEnded();
}
所以我们可以在go方法中写入一个简单的循环,如下代码所示:
while(true)
{
// Pump window messages for nice behaviour
Ogre::WindowEventUtilities::messagePump();
if(mWindow->isClosed())
{
return false;
}
// Render a frame
if(!mRoot->renderOneFrame()) return false;
}
这样,直到窗口关闭,或者renderOneFrame()返回false,Ogre不会停止对窗体的渲染。