(注:本文假设你读过前三节)
使用COgreSceneBox只能对一个Static进行3D场景的渲染,如何对多个Static同时进行3D渲染呢?改动的步骤很直观:
1. 先尝试建立多个COgreSceneBox的对象,编译。。。运行。。。,结果窗口没出来就弹出了一个断言错误, ms_Singleton != 0,为什么会这样呢?这要从OGRE的内部设计分析,OGRE将Root对象派生于Singleton模版,熟悉设计模式的程序员都知道Root实际上被设计成了单件模式,也就是只能有一个对象。
2. 既然知道Root只能有一个对象,那么所有对Root的初始化和释放操作都必须只运行一次,根据这个对COgreSceneBox的代码进行改动:
//
Init ogre
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
BOOL Initialize()
...
{
// already inited
FALSE_RETURN( (m_pRoot == NULL), TRUE );
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
T* pT = static_cast<T*>(this);
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
if(Root::getSingletonPtr() == NULL)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
// create scene root with no config file and plugin
m_pRoot = new Root("", "");
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
// Load plugin
FALSE_RETURN( pT->LoadPlugin(), FALSE );
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
// Select Render System
FALSE_RETURN( pT->SelectRenderSystem(), FALSE );
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
m_pRoot->initialise(false, TBase::GetWndClassName());
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
// Load Resource
FALSE_RETURN( pT->LoadResource(), FALSE );
}
else
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
...{
m_pRoot = Root::getSingletonPtr();
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
// Create Render Window
FALSE_RETURN( pT->CreateRenderWindow(), FALSE );
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
// Create Scene Manager
FALSE_RETURN( pT->CreateSceneManager(), FALSE );
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
// Create Default Camera and Viewport
FALSE_RETURN( pT->CreateDefaultCamera(), FALSE );
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
// Create Scene
FALSE_RETURN( pT->CreateScene(), FALSE );
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
return TRUE;
}
代码将 加载插件、选择渲染系统、加载资源 放到if()...else()判断中,使这些代码只执行一次,这里多嘴一句,OGRE好像只能在同一个Root中使用同一种渲染系统(OpenGL/D3D),无法在同一时刻使用两种系统,甚至在系统切换时需要重新构建所有资源和窗口。
3. 改动代码后我们再编译、运行(这里我多加了5个Static,每个static控件对应一个COgreSceneBox的对象),OK,出来了!但是关闭的时候出了个问题:又是ms_Singleton的断言错误,仔细想了一下,肯定是释放的时候多次delete了,于是像构造一样确保Root的释放只发生一次(我的处理方案是在整个程序退出时释放Root),OK,这次应该没有什么问题了。
为了演示效果,我从COgreSceneBox派生了一个类CExampleSceneBox,让原来静止的食人魔以一定速度绕Y轴旋转,下图是6个食人魔,由六个static控件分别渲染,并以不同的速率和方向进行旋转:
![](https://p-blog.csdn.net/images/p_blog_csdn_net/DRACULAX05/1.bmp)