本博文讲述利用Visual Studio 2019、Osg、Qt搭建三维开发环境。本次Qt版本为5.14.1,Window为Windows 10。osg可以去osg下载,截至2022年8月21日,osg最新版本已经到3.6.5版本,考虑到最新版本的往往有些许的bug,故本文采用的是3.4.1版本,其下载地址为:OpenSceneGraph-3.4.1 release download
osg在Windows下的 编译安装参见《windows平台下用CMake编译osg》。
注意:在利用CMake生成OpenSceneGraph.sln时,该解决方案的OSG Core文件夹下有的电脑会有osgQt工程 ,有的则没有,如:我公司电脑有osgQt工程,而我自己笔记本则没有,环境都一样,原因至今不知道。编译完成后,我的目录结构如下:
在Visual Studio 2019下创建一个osg的Qt工程,cpp代码代码如下:
#include "QtWidgetsApplication2.h"
#include
QtWidgetsApplication2::QtWidgetsApplication2(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
initOsg();
}
QtWidgetsApplication2::~QtWidgetsApplication2()
{}
void QtWidgetsApplication2::initOsg()
{
// 步骤一:初始化qt窗口系统
osgQt::initQtWindowingSystem();
// 步骤二:创建视口
m_pViewer = new osgViewer::Viewer;
// 步骤三:视口设为单线程(Qt5必须)
m_pViewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
// 步骤四:对视图的操作,必须,否则无法显示黑屏
m_pViewer->setCameraManipulator(new osgGA::TrackballManipulator);
// 步骤五:视口操作
// 步骤六:设置osgQt视口(一个应用程序用opgQt同一时刻只能设置一个视口)
osgQt::setViewer(m_pViewer.get());
// 步骤七:创建窗口(2个都要,只创建osgQt::GLWidget会挂掉)
m_pGLWidget = new osgQt::GLWidget(this);
m_pGraphicsWindowQt = new osgQt::GraphicsWindowQt(m_pGLWidget);
// 步骤八:设置视口
m_pViewport = new osg::Viewport(0, 0, m_pGLWidget->width(), m_pGLWidget->height());
//m_pViewport = new osg::Viewport();
// 步骤九:设置摄像机视口范围,未设置不会显示,即窗口一片黑(刷新窗口但没有内容显示)
m_pViewer->getCamera()->setViewport(m_pViewport);
m_pViewer->getCamera()->setClearColor(osg::Vec4f(0.0235, 0.45, 0.67, 1.0));
// 步骤十:设置刷新显示内容,未设置不会显示,即一片白(不会刷新窗口)
m_pViewer->getCamera()->setGraphicsContext(m_pGraphicsWindowQt);
auto spCowNode = osgDB::readNodeFile("cow.osg");
m_pViewer->setSceneData(spCowNode );
}
void QtWidgetsApplication2::resizeEvent(QResizeEvent* event)
{
m_pGLWidget->move(0, 0);
m_pGLWidget->resize(event->size());
}
.h代码如下:
#pragma once
#include
#include "ui_QtWidgetsApplication2.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
class QtWidgetsApplication2 : public QWidget
{
Q_OBJECT
public:
QtWidgetsApplication2(QWidget *parent = nullptr);
~QtWidgetsApplication2();
void initOsg();
void resizeEvent(QResizeEvent* event) override;
private:
Ui::QtWidgetsApplication2Class ui;
// osg about
osg::ref_ptr m_pViewer{ nullptr };
osg::ref_ptr m_pViewport{ nullptr };
osgQt::GLWidget* m_pGLWidget{ nullptr };
osg::ref_ptr < osgQt::GraphicsWindowQt> m_pGraphicsWindowQt{ nullptr };
};
生成目录、包含目录、库目录、链接库设置如下:
图2:包含目录、库目录
图3:链接库设置
为了保证链接设置完全,我们把osg的核心库都加入,如下:
OpenThreadsd.lib
osgd.lib
osgDBd.lib
osgGAd.lib
osgManipulatord.lib
osgTextd.lib
osgUId.lib
osgUtild.lib
osgViewerd.lib
osgWidgetd.lib
osgQtd.lib
注意:这是debug版的lib,release版的去掉文件名的最后一个d即可。
当编译2节的工程时,会出现很多问题。
解决方法:将E:\osg\build\include下子目录下的文件拷贝到
E:\osg\OpenSceneGraph-3.4.1\include目录下与其子目录名相同的目录中。
无法打开包括文件: “osgQt/Version”: No such file or directory
找到E:\osg\OpenSceneGraph-3.4.1\src\osgQt目录下的Version.in文件拷贝到E:\osg\OpenSceneGraph-3.4.1\include\osgQt并重命名为Version,用记事本打开该文件并将下面删除:
#if (QT_VERSION < QT_VERSION_CHECK(OSGQT_QT_VERSION,0,0))
#error "Qt version mismatch detected! Make sure to compile applications using osgQt with the same major Qt version that osgQt has been compiled against."
#endif
否则会报: error C2018: 未知字符“0x40”。
解决方案的OSG Core文件夹下有osgQt工程,则直接链接osgQt,QtWidgetsApplication2工程启动,但立马崩溃,崩溃于:osg\State.cpp的第229行,如下:
_glExtensions->glGetQueryiv(GL_TIMESTAMP, GL_QUERY_COUNTER_BITS_ARB, &bits);
发现_glExtensions的glGetQueryiv函数指针没初始化,是随机值。解决方案的OSG Core文件夹下没有osgQt工程,则不会生成osgQtd.lib,则会报找不到osgQtd.lib。
从3节遇到的问题我们知道,osg自带的osgQt工程会导致主程序崩溃;没有osgQt工程,则会报找不到osgQtd.lib。那么我们手动创建osgQt工程,以生成osgQtd.lib。
打开Visual Studio 2019,选择创建Qt Class Library,工程名为osgQt,工程保存目录为:
E:\osg\build\src ,从工程中移除osgQt.h、osgQt.cpp。将E:\osg\OpenSceneGraph-3.4.1\src\osgQt目录下的所有cpp文件和E:\osg\OpenSceneGraph-3.4.1\include\osgQt目录下的所有文件拷贝到刚新建的E:\osg\build\src\osgQt目录下,并在VS2019中将这些文件添加到工程中(Export、Version可以不添加)。之后将QFontImplementation.cpp头部的
#include
#include
。 按2节描述的那样为该工程添加包含目录、库目录、链接库(注意:osgQtd.lib就不要添加了)。设置Qt的模块如下:
图4
设置生成的debug版本的文件名带一个d且设置输出目录,如下:
图5
编译osgQt,报如下错误:
即 “graphicswindow_Qt”: 不允许 dllimport 函数 的定义。找到Export文件,在文件顶部加入如下宏定义: #define OSGQT_LIBRARY,如下:
,如果还不行,将该Export的所有行都注释,加入:
#define OSGQT_EXPORT __declspec(dllexport)
再次编译,报如下链接错误:
产生这些错误的原因是QGraphicsViewAdapter类没生成元对象有关的cpp文件,也就是如下红色方框的属性节点在编译时消失导致不能生成moc文件,原因费解 。
打开cmd或power shell,cd到当前目录,执行如下命令:
即:
C:\Qt\Qt5.14.1\5.14.1\msvc2017_64\bin\moc.exe QGraphicsViewAdapter -o moc_GraphicsViewAdapter.cpp
其中C:\Qt\Qt5.14.1\5.14.1是你Qt在本机的安装目录,此时会在当期目录下生成moc_GraphicsViewAdapter.cpp,将该文件添加到osgQt工程,再次编译就成功了,此时在E:\osg\build\bin目录下就有osgQtd.dll、osgQtd.lib。将osgQtd.lib复制到E:\osg\build\lib目录。将从Osg官网下载的cow.osg、reflect.rgb文件拷贝到QtWidgetsApplication2工程,并启动该工程,效果如下:
注意:reflect.rgb也要拷贝,否则牛是白色的,不会是彩色的。
至此,Windows下的osg和Qt开发环境配置完成。
现在osg使用QT做窗口系统的工程剥离出去了,在 https://github.com/openscenegraph/osgQt 我们可以下载到osg使用QT窗口的工程,其中osgQt/examples/osgQtWidgets/osgQtWidgets.cpp中对使用Qt创建窗口使用OSG进行绘制有详细的示例。