1、首先要在vs2010中创建一个基于qt的QWidge工程(OsgQtTest),然后对osgqtest.h进行修改,如下代码:
#ifndef OSGQTTEST_H #define OSGQTTEST_H #include <osgLib.h> #include <QtCore/QTimer> #include <QtWidgets/QApplication> #include <QtWidgets/QVBoxLayout> #include <QtWidgets/QWidget> #include <osgViewer/CompositeViewer> #include <osgViewer/ViewerEventHandlers> #include <osgGA/TrackballManipulator> #include <osgDB/ReadFile> #include <osgQt/GraphicsWindowQt> #include <iostream> //CompositeViewer是多视景器 //Viewer是单视景器 class OsgQtTest : public QWidget,public osgViewer::CompositeViewer { Q_OBJECT public: OsgQtTest(osgViewer::ViewerBase::ThreadingModel threadingModel=osgViewer::CompositeViewer::SingleThreaded); ~OsgQtTest(); QWidget* addViewWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene ); osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name="", bool windowDecoration=false ); virtual void paintEvent( QPaintEvent* event ); protected: QTimer _timer; }; #endif // OSGQTTEST_H2、osgqttest.cpp代码:
#include "osgqttest.h" OsgQtTest::OsgQtTest(osgViewer::ViewerBase::ThreadingModel threadingModel): QWidget() { /*设置线程模式,线程模式包括: SingleThreaded表示单线程模式,OSG 不会创建任何新线程来完成场景的筛选和渲染,因而也不会对渲染效率的提高有任何助益。它适合任何配置下使用。 CullDrawThreadPerContext:OSG 将为每一个图形设备上下文(GraphicsContext)创建一个图形线程,以实现并行的渲染工作。如果有多个CPU 的话, 那么系统将尝试把线程分别放在不同的CPU 上运行,不过每一帧结束前都会强制同步所有的线程。 ThreadPerContext DrawThreadPerContext:这一线程模型同样会为每个GraphicsContext 创建线程,并分配到不同的CPU 上。十分值得注意的是,这种模式会在当前帧的所有 线程完成工作之前,开始下一帧。 CullThreadPerCameraDrawThreadPerContext:这一线程模型将为每个GraphicsContext和每个摄像机创建线程,这种模式同样不会等待前一次的渲染结束, 而是返回仿真循环并再次开始执行frame 函数。如果您使用四核甚至更高的系统配置,那么使用这一线程模型将最大限度地发挥多CPU 的处理能力。 ThreadPerCamera AutomaticSelection */ setThreadingModel(threadingModel); // disable the default setting of viewer.done() by pressing Escape. setKeyEventSetsDone(0);//来设置自定义的退出键(缺省是GUIEventAdapter::KEY_Escape)。 //在坐标(0,0)处创建一个窗口,并将cow.osgt设置到该窗口中 QWidget* widget1 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readNodeFile("cow.osgt") ); QWidget* widget2 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readNodeFile("glider.osgt") ); QWidget* widget3 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readNodeFile("axes.osgt") ); QWidget* widget4 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readNodeFile("fountain.osgt") ); //在坐标(900,100)处创建一个窗口,并将dumptruck.osgt设置到该窗口中 QWidget* popupWidget = addViewWidget( createGraphicsWindow(900,100,320,240,"Popup window",true), osgDB::readNodeFile("dumptruck.osgt") ); //以非模态窗口显示,此窗口是与主窗口分割开的 popupWidget->show(); QGridLayout* grid = new QGridLayout;//创建一个网络布局 grid->addWidget( widget1, 0, 0 );//在第0行,0列添加一个窗口 grid->addWidget( widget2, 0, 1 );//在第0行,1列添加一个窗口 grid->addWidget( widget3, 1, 0 );//在第1行,0列添加一个窗口 grid->addWidget( widget4, 1, 1 );//在第1行,1列添加一个窗口 setLayout( grid );//将该布局设置到主窗口中 connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) ); _timer.start( 10 ); } OsgQtTest::~OsgQtTest() { } QWidget* OsgQtTest::addViewWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene ) { osgViewer::View* view = new osgViewer::View;//创建一个渲染器 addView( view );//将渲染器加入到窗口中去 osg::Camera* camera = view->getCamera();//获得渲染器中的相机 //视景器Viewer 的主/从摄像机均需要使用setGraphicsContext设置对应的图形设备上下文,实际上也就是对应的显示窗口,那么gw就是要显示的窗口 camera->setGraphicsContext( gw ); const osg::GraphicsContext::Traits* traits = gw->getTraits();//可通过窗口的getTraits获得窗口的属性 camera->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) );//设置清除缓存区背景的颜色。RGBA格式。 camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );//设置视口的尺寸与位置。 //以透视投影的方式来设置投影矩阵。30为透视投影中的视角,第二个参数一般都是窗口的宽/高,第三个参数投影钟的近视角,第四个参数为投影钟的远视角 camera->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 1.0f, 10000.0f ); view->setSceneData( scene );//将模型添加到渲染器中 view->addEventHandler( new osgViewer::StatsHandler );//添加一些常用状态设置 view->setCameraManipulator( new osgGA::TrackballManipulator );//设置一个操作器 return gw->getGLWidget();//获得窗口对象,相当于QWidget*,可通过此对象对界面进行设置以及添加到当前的window中 } osgQt::GraphicsWindowQt* OsgQtTest::createGraphicsWindow( int x, int y, int w, int h, const std::string& name, bool windowDecoration) { osg::DisplaySettings* ds = osg::DisplaySettings::instance().get(); //声明一个嵌入窗口的变量,只要是有多个窗口必须使用此对象进行设置 osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; traits->windowName = name;//设置窗口的标题 traits->windowDecoration = windowDecoration;//是否显示窗口的描述,默认为false不显示 traits->x = x;//设置窗口显示的x坐标 traits->y = y;//设置窗口显示的y坐标 traits->width = w;//设置窗口的宽度 traits->height = h;//设置窗口的高度 traits->doubleBuffer = true;//创建新的图形窗口是否使用双缓冲特性 traits->alpha = ds->getMinimumNumAlphaBits();//获得最小透明值 traits->stencil = ds->getMinimumNumStencilBits();//获得模板缓存的最小位数 traits->sampleBuffers = ds->getMultiSamples(); traits->samples = ds->getNumMultiSamples(); return new osgQt::GraphicsWindowQt(traits.get());//通过以上的设置参数来创建一个qt的窗口对象 } void OsgQtTest::paintEvent( QPaintEvent* event ) { /* frame()函数的源代码如下: void ViewerBase::frame(double simulationTime) { if (_done) return; // OSG_NOTICE<<std::endl<<"CompositeViewer::frame()"<<std::endl<<std::endl; if (_firstFrame) { viewerInit();//如果这是仿真系统启动后的第一帧,则执行viewerInit() if (!isRealized())//viewerInit();此时如果还没有执行realize()函数,则执行它。 { realize(); } _firstFrame = false; } advance(simulationTime);//执行advance 函数 //执行eventTraversal 函数,顾名思义,这个函数将负责处理系统产生的各种事件,诸 //如鼠标的移动,点击,键盘的响应,窗口的关闭等等,以及摄像机与场景图形的事件回调 //(EventCallback)。 eventTraversal(); //执行updateTraversal 函数,这个函数负责遍历所有的更新回调(UpdateCallback); //除此之外,它的另一个重要任务就是负责更新DatabasePager 与ImagePager 这两个重要的分 //页数据处理组件。 updateTraversal(); //执行renderingTraversals 函数,这里将使用较为复杂的线程处理方法,完成场景的筛选(cull)和绘制(draw)工作。 renderingTraversals(); } */ frame();//实时对其进行渲染 }
#include "osgqttest.h" #include <QtWidgets/QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); OsgQtTest* viewWidget = new OsgQtTest(); viewWidget->setGeometry( 100, 100, 640, 480 ); viewWidget->show(); return a.exec(); }