本文内容已经移至我最新的个人博客,欢迎大家到我的新网站交流学习。 查看文章请点我。
最近做了一段时间的CEGUI和OSG之间的结合,有一点小小的收获。写一篇文章来记录所做的一点点事情。
下面写一点CEGUI和OSG之间结合的东西。
一.整体过程概述:
CEGUI作为OSG的Drawable集成到OSG中。CEGUI继承osg::Drawable类,作为一个Drawable完成初始化,加入到一个节点中(osg::Geode)。然后将该节点在Viewerd执行realize()之后加入到osg::Group对象中。即可将CEGUI集成到OSG中。
示例过程代码:
int main() { osgViewer::Viewer* viewer = new osgViewer::Viewer(); osg::ref_ptr<osg::Group> gp = new osg::Group; gp->addChild(osgDB::readNodeFile("cow.osg")); viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);//设置单线程模式 viewer->realize(); viewer->getCamera()->getGraphicsContext()->makeCurrent(); osg::ref_ptr<osg::Geode> gnode = new osg::Geode; osg::ref_ptr<osg::StateSet> stateset = gnode->getOrCreateStateSet(); stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);//光线 stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);//这个设置决定了是CEGUI窗口可以遮挡OSG模型处于最前面。 osg::ref_ptr<CEGUIDrawable> cd = new CEGUIDrawable(); gnode->addDrawable(cd.get());//Drawable加入到节点中 cd->InitCEGUIScene();//CEGUI初始化 ////////////////////////////////////////////////////////////// gp->addChild(gnode); viewer->getCamera()->getGraphicsContext()->releaseContext(); viewer->setSceneData(gp); viewer->addEventHandler(new ChangeWindow); viewer->run(); return 0; }
二.CEGUI的绘制过程:
1. 在构造函数中初始化CEGUI的资源文件路径。包括以下7类资源文件(schemes;imagesets;fonts;looknfeel;layouts;lua_scripts;animations;)。经常修改使用的是imagesets和layouts。这个与窗口布局相关以及所使用的资源图片相关。
2. 读取所绘制的窗体的需要的资源。该资源读取过程有两种方式实现。
(1) 直接读取:
void CEGUIDrawable::InitCEGUIScene(){ SchemeManager::getSingleton().create("Demo8.scheme"); ImagesetManager::getSingleton().create("ToolbarIcons.imageset"); WindowManager& winMgr = WindowManager::getSingleton (); Window* root = winMgr.loadWindowLayout("Toolbar.layout"); System::getSingleton().setGUISheet(root); System::getSingleton().setDefaultTooltip("TaharezLook/Tooltip"); }
通过以上语句可以根据需要读取到自己需要的主题文件、图片集文件、布局文件。这样窗体绘制的文件读入完成。
(2)间接读取:
void CEGUIDrawable::InitCEGUIScene() { using namespace CEGUI; LuaScriptModule& scriptmod(LuaScriptModule::create());// create a script module. System::getSingleton().setScriptingModule(&scriptmod); // tell CEGUI to use this scripting module System::getSingleton().executeScriptFile("demo8.lua");// execute the demo8 script which controls the rest of this demo }
间接读取即CEGUI直接读取脚本文件,相关资源的读取以及相关事件的处理放到脚本文件中进行。脚本文件使用LUA编写。
3.通过以上两个步骤,CEGUI即绘制完成。在OSG的仿真循环方法realize()之后执行
viewer->getCamera()->getGraphicsContext()->makeCurrent(); osg::ref_ptr<osg::Geode> gnode = new osg::Geode; osg::ref_ptr<osg::StateSet> stateset = gnode->getOrCreateStateSet(); stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);//光线 stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);//这个设置决定了是CEGUI窗口可以遮挡OSG模型处于最前面。 osg::ref_ptr<CEGUIDrawable> cd = new CEGUIDrawable(); gnode->addDrawable(cd.get());//Drawable加入到节点中 cd->InitCEGUIScene();//CEGUI初始化 ////////////////////////////////////////////////////////////// gp->addChild(gnode);
便将CEGUI的绘制的窗体加入到了OSG中。
三.CEGUI窗体的绘制过程。
CEGUI支持两种方式的窗体绘制使用,一种就是直接在c++文件当中创建窗体,使用窗体;另一种方式就是在layout文件当中定制窗体。从理论上讲,两种方式都能达到相同的目的。
在不使用layout文件时,CEGUI是不太方便的,因为要定位控件,常常得修改文件当中的参数,如果在c++文件当中修改,每次都需要编译。
代码实例:
(1) 直接绘制:
FrameWindow* wnd = (FrameWindow*)winMgr.createWindow("TaharezLook/FrameWindow", "Demo Window"); root->addChildWindow(wnd); wnd->setPosition(UVector2(cegui_reldim(0.25f), cegui_reldim( 0.25f))); wnd->setSize(UVector2(cegui_reldim(0.5f), cegui_reldim( 0.5f))); wnd->setMaxSize(UVector2(cegui_reldim(1.0f), cegui_reldim( 1.0f))); wnd->setMinSize(UVector2(cegui_reldim(0.1f), cegui_reldim( 0.1f))); wnd->setText("Hello World!"); Checkbox* check1 = static_cast<Checkbox*>(CEGUI::WindowManager::getSingleton().createWindow("TaharezLook/Checkbox", "Cessna1")); check1->setText("no selected1"); check1->setPosition(CEGUI::UVector2(cegui_reldim(0.1f), cegui_reldim(0.2))); check1->setSize(CEGUI::UVector2(cegui_reldim(0.3f), cegui_reldim(0.06))); wnd->addChildWindow(check1); Checkbox* check2 = static_cast<Checkbox*>(CEGUI::WindowManager::getSingleton().createWindow("TaharezLook/Checkbox", "Cessna2")); check2->setText("no selected2"); check2->setPosition(CEGUI::UVector2(cegui_reldim(0.1f), cegui_reldim(0.4))); check2->setSize(CEGUI::UVector2(cegui_reldim(0.3f), cegui_reldim(0.06))); wnd->addChildWindow(check2); CEGUI::Scrollbar* stn2 = static_cast<CEGUI::Scrollbar*>(CEGUI::WindowManager::getSingleton().createWindow("TaharezLook/HorizontalScrollbar", "scrb")); wnd->addChildWindow(stn2); stn2->setPosition(CEGUI::UVector2(cegui_reldim(0.1f), cegui_reldim(0.6))); stn2->setSize(CEGUI::UVector2(cegui_reldim(0.5f), cegui_reldim(0.06))); stn2->setStepSize(0.1); stn2->setOverlapSize(0.1);
(2) 间接绘制:
CEGUI::WindowManager& winMgr = CEGUI::WindowManager::getSingleton(); child =static_cast<CEGUI::FrameWindow*>(winMgr.loadWindowLayout("MeasureWindow.layout"));
使用布局文件编辑器编辑好布局后直接通过上述两句代码即可实现直接绘制所看到的效果图。所以布局文件的使用可以使得布局的设计变得方便。