如题,工作需要将一个3D显示放到界面中。本文记录了一个OSG新手,把"cow.osg"显示到Qt窗体中的完整过程。
一、简单介绍下OSG:OpenSceneGraph
OSG是一个开源的三维引擎,被广泛的应用在可视化仿真、游戏、虚拟现实、科学计算、三维重建、地理信息、太空探索、石油矿产等领域。OSG采用标准C++和OpenGL编写而成,可运行在所有的Windows平台、OSX、GNU/Linux、IRIX、Solaris、HP-Ux、AIX、Android和FreeBSD 操作系统。
我的理解是,OpenGL开发比较难,OSG提供了一个跨平台的易实现的调用接口。
二、准备工作
鉴于我的需求,先不做OSG源码编译,直接下载编译好的库。下载:OSG编译库
本文使用版本为:OpenSceneGraph-3.6.4-VC2017-64-Release;安装:MSVC2017+Qt5.13.2
三、开始调试
3.1 新建Qt工程,修改代码
如下为源码,pro 和 h 文件只列了编辑部分;osg库链接部分可以工程右键添加库,找到库所在路径;
ui中只添加了一个水平布局组件:horizontalLayoutOSG
工程右键添加资源文件,并添加 cow.osg 到资源文件;cow.osg依赖文件放在同一路径下即可。
文件读取,路径处理有三种方式:绝对路径,当前工作路径,资源文件URL;注意当前路径,不确定的请看看Project编译运行设置页 Working Directory;
//xxx.pro
QT += core gui opengl
win32: LIBS += -L$$PWD/../../../Libs/OSG364/lib/ -losgQt5 -losg -lOpenThreads \
-losgViewer -losgDB -losgGA
INCLUDEPATH += $$PWD/../../../Libs/OSG364/include
DEPENDPATH += $$PWD/../../../Libs/OSG364/include
RESOURCES += \
resources.qrc
//mainwindow.h
#include <QTimer>
#include <osgViewer/Viewer>
#include <osgViewer/CompositeViewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgQt/GraphicsWindowQt>
#include <osgGA/StateSetManipulator>
#include <osgDB/ReadFile>
private:
Ui::MainWindow *ui;
QTimer* _timer;
osgViewer::Viewer viewer;
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//设置模型
osg::ref_ptr<osg::Group> root = new osg::Group;
// osg::ref_ptr<osg::Node> child = osgDB::readNodeFile("D:\\Developer\\Qt5.13.2\\Workspace\\build-untitled-Desktop_Qt_5_13_2_MSVC2017_64bit-Release\\release\\cow.osg");
// osg::ref_ptr<osg::Node> child = osgDB::readNodeFile("cow.osg");
osg::ref_ptr<osg::Node> child = osgDB::readNodeFile("qrc:/osg/cow.osg");
root->addChild(child);
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->windowDecoration = false;//声明是否显示窗口的描述
traits->x = 50;
traits->y = 50;
traits->width = 800;
traits->height = 600;
traits->doubleBuffer = true;//创建图形窗口是否使用双缓存
//设置照相机
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setGraphicsContext(new osgQt::GraphicsWindowQt(traits.get()));
camera->setClearColor(osg::Vec4(0.2f, 0.2f, 0.6f, 1));
camera->setViewport(new osg::Viewport(0, 0, 800, 600));
camera->setProjectionMatrixAsPerspective(30, 800.0/600.0, 1, 10000);
//设置渲染器
viewer.setCamera(camera);
viewer.setSceneData(root);
viewer.setCameraManipulator(new osgGA::TrackballManipulator);
viewer.setThreadingModel(osgViewer::Viewer::SingleThreaded);//创建为单线程
viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));
viewer.addEventHandler(new osgViewer::WindowSizeHandler);
viewer.addEventHandler(new osgViewer::StatsHandler);
osgQt::GraphicsWindowQt* gw = dynamic_cast<osgQt::GraphicsWindowQt*> (camera->getGraphicsContext());
ui->horizontalLayoutOSG->addWidget(gw->getGLWidget());
_timer = new QTimer;
connect(_timer, SIGNAL(timeout()), this, SLOT(slotUpdate()));
_timer->start(25);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::slotUpdate() {
viewer.frame();
}
3.2 QtCreator编译执行
Build选择Release,执行
主窗口显示如下图,鼠标拖动可使三维图变动;
3.3 独立EXE执行
将依赖库所在路径添加到系统变量Path中,包括OSG库和Qt5
将cow.osg及依赖文件放到exe路径下;
exe执行仍报错:osgQt5,而Qt5动态库已经设系统变量;这是由于实际调用的Qt库并非正确的Qt库;
如下图所示,用Depends工具,分析osgQt5.dll。可以发现其调用的Qt动态库,实际上matlab路径下的,而与osg库依赖的Qt库的版本不一致。
解决办法是:环境变量Path 中去掉这个错误的路径;或将这个路径放到正确路径的后边;
最终,EXE直接运行成功,与QtCreator中运行效果一致。
后续,深入OSG应用调试,感谢交流指正!