项目需要用到osg,Qt和vs2010结合,这几天一直在搞这个事情,遇到了很多困难,在这里记录一下
以我的经历强调几个重点,这几个点最好在编译之前就解决了,不然太浪费时间 。都是个人意见仅供参考。
1. 把osg嵌入Qt最好用Qt4,推荐选择Qt4.8 。两个原因,一是Qt5据说是支持单线程 的,我先前觉得Qt4太旧了,选择了几个Qt5的版本,好不容易编译成功了,最后使用的时候遇到线程的问题“Cannot make QOpenGLContext current in a different thread.”,始终没找到解决方法,放弃了。二是Qt4.6(好像是的)以前的版本需要编译,直接用Qt4.8版本有编译好的适用于vs2010的版本。
2. 如果真的要编译osg+Qt5的话一定要检查这个文件:/src/osgQt/CMakeLists.txt ,具体原因链接里面看: http://blog.csdn.net/BenBenDeYiZhi/article/details/78847441
3.在vs2010+Qt4环境下编译osg的过程需要注意两个很重要的点:
一是开始编译之前一定不要忘记
修改osg根目录下的Cmakelist.txt文件,在末尾添加如下两句:
set(DESIRED_QT_VERSION "4.8.6" CACHE STRING "")
set(CMAKE_PREFIX_PATH "D:\qt\4.8.6" CACHE PATH "") (注意把 D:\qt\4.8.6换成你自己的qt路径 )
二是用vs2010生成osg文件的时候一定要记得打开vs2010的方式是“以管理员的身份打开”,并且一旦生成在D盘,就不能再把生成的osg文件移到C盘使用 (我的是这样,不知道为什么,我试着把编译生成的库,头文件啥的移动到C盘,最后命令行运行osgversion命令的时候出错“无法找到ot13-OpenThreads.dll入口点”啥的,记不清了)
4.经常遇到的错类型:
一是编译时无法打开某个头文件,如QGLwidget头文件,基本上是需要吧头文件所在的路径加入到项目属性-->VC++目录-->包含文件下,QGLWidget在Qt\Qt4.8.6\include\QtOpenGL里面。
二是编译时出现“error LNK2019: 无法解析的外部符号 "__declspec(dllimport) ”错误,一般都是因为缺少相关的库文件,仔细查看错误,看看错误跟哪个函数或类有关,继而找到这个函数所在的头文件,从而可以推断出这个类所在的库文件(.lib文件),把库文件名添加到项目属性-->连接器-->输入 里面就好了(但是有一个前提,这个库的路径一定得在环境变量path里面)。
5.osg的第三方库可以直接选用已经编译好的,无需自己编译,节省时间。第一次编译的时候可以不用勾选编译osg自带的例子,毕竟不一定成功,等真的编译成功了可以再挑选个晚上的时间重新编译带例子的,个人习惯呀,大家自便了这个。
下面贴一下qt+osg+vs2010环境搭建的具体步骤的参考链接:
Qt5.5+osg3.2+vs2010 环境搭建参考链接1:http://blog.csdn.net/bbppbb/article/details/45697731
参考链接2: http://blog.sina.com.cn/s/blog_89a45b020102whh8.html
Qt4.8.6+osg3.2+vs2010 环境搭建参考链接:http://blog.sciencenet.cn/blog-419883-955964.html
最后的测试:
先检测osg的有没有安装成功,打开命令行,输入osgversion,输出osg版本信息,输入osgviewer cow.osg出现牛。然后打开vs,新建一个QtApplication(直接点击完成就好),配置好项目属性里面的包含目录和库目录,配置好附加依赖项,把如下代码复制到主函数,覆盖原来的主函数即可,如果出现错误提示,把错误排除(比如包含目录错误,打开文件错误等等),完成后如果程序运行成功(参考最后给出的链接),一切完事了,恭喜~
代码:
#include <QTimer> #include <QApplication> #include <QGridLayout> #include <QWidget> #include <osgViewer/CompositeViewer> #include <osgViewer/ViewerEventHandlers> #include <osgGA/TrackballManipulator> #include <osgDB/ReadFile> #include <osgQt/GraphicsWindowQt> #include <iostream> class ViewerWidget : public QWidget, public osgViewer::CompositeViewer { public : ViewerWidget(osgViewer::ViewerBase::ThreadingModel threadingModel=osgViewer::CompositeViewer::SingleThreaded) : QWidget() { setThreadingModel(threadingModel); setKeyEventSetsDone(0); 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" ) ); 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 ); grid->addWidget( widget2, 0, 1 ); grid->addWidget( widget3, 1, 0 ); grid->addWidget( widget4, 1, 1 ); setLayout( grid ); connect( &_timer, SIGNAL(timeout()), this , SLOT(update()) ); _timer.start( 10 ); } QWidget* addViewWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene ) { osgViewer::View* view = new osgViewer::View; addView( view ); osg::Camera* camera = view->getCamera(); camera->setGraphicsContext( gw ); const osg::GraphicsContext::Traits* traits = gw->getTraits(); camera->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) ); camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) ); 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(); } osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name= "" , bool windowDecoration= false ) { osg::DisplaySettings* ds = osg::DisplaySettings::instance().get(); osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; traits->windowName = name; traits->windowDecoration = windowDecoration; traits->x = x; traits->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()); } virtual void paintEvent( QPaintEvent* event ) { frame(); } protected : QTimer _timer; }; int main( int argc, char ** argv ) { osg::ArgumentParser arguments(&argc, argv); osgViewer::ViewerBase::ThreadingModel threadingModel = osgViewer::ViewerBase::CullDrawThreadPerContext; while (arguments.read( "--SingleThreaded" )) threadingModel = osgViewer::ViewerBase::SingleThreaded; while (arguments.read( "--CullDrawThreadPerContext" )) threadingModel = osgViewer::ViewerBase::CullDrawThreadPerContext; while (arguments.read( "--DrawThreadPerContext" )) threadingModel = osgViewer::ViewerBase::DrawThreadPerContext; while (arguments.read( "--CullThreadPerCameraDrawThreadPerContext" )) threadingModel = osgViewer::ViewerBase::CullThreadPerCameraDrawThreadPerContext; QApplication app(argc, argv); ViewerWidget* viewWidget = new ViewerWidget(threadingModel); viewWidget->setGeometry( 100, 100, 800, 600 ); viewWidget->show(); return app.exec(); }
代码参考链接: http://blog.csdn.net/zhaohsww/article/details/19085211