OSG环境搭建(OSG3.6.2+VS2017+Qt5.10.1
2018-07-30 本文已影响3814人
downdemo
编译OSG3.6.2
- 编译过程参考Compiling with Visual Studio,VS要求已安装MFC,需要的安装包可在osgChina或OSG官网获取。以下是此次编译过程中所用的工具版本及其下载地址:
- 源码包:OpenSceneGraph-3.6.2.zip
- 第三方库依赖:VS2017全部依赖64位
- 数据包:OpenSceneGraph-Data-3.4.0.zip
- CMeke:cmake-3.12.0-win64-x64.msi
- VS2017
- 新建
E:\OSG,将上述前三个包解压到此目录
E:\OSG
- 为了后续方便,将解压后的目录分别改名为
3rdParty、Data、OpenSceneGraph
改名后
- 在
E:\OSG\OpenSceneGraph新建一个build文件夹用于存放编译内容
新建一个build文件夹
- 安装
cmake-3.12.0-win64-x64.msi并重启,完成后打开CMake (cmake-gui)
CMake (cmake-gui)
- 将
E:\OSG\OpenSceneGraph\CMakeLists.txt拖到CMake (cmake-gui)中
将CmakeLists.txt拖进CMake后
- 将构建路径改为之前新建的
E:/OSG/OpenSceneGraph/build
构建路径改为E:/OSG/OpenSceneGraph/build
- 点击
Configure,为了生成64位版本,选择Visual Studio 15 2017 Win64。注意,如果此处选择Visual Studio 15 2017则将生成32位版本
选择Visual Studio 15 2017 Win64
- 选好后点击
Finish
此时即可点击Finish
- 等待大概二十秒完成Configure
Configure中
- Configure完成后修改如下几个选项
ACTUAL_3RDPARTY_DIR:E:/OSG/3rdParty
BUILD_OSG_EXAMPLES:打勾
CMAKE_INSTALL_PREFIX:E:/OSG/OpenSceneGraph/build
可用Search快速找到选项
- 第二次点击
Configure,将BUILD_MFC_ EXAMPLE打勾,勾选Advanced
第二次点击Configure后勾选BUILD_MFC_ EXAMPLE
- 第三次点击
Configure,完成后界面将没有红色选项
第三次点击Configure后
- 点击
Generate
Generate中
- Generate完成,提示
Generating done,至此可关闭cmake-gui
Generating done
- 用VS2017打开
E:\OSG\OpenSceneGraph\build\OpenSceneGraph.sln
OpenSceneGraph.sln
- 等待加载完成,CMake构建的解决方案一般包含三个工程:
ALL_BUILD、INSTALL和ZERO_CHECK
- 只要编译
ALL_BUILD就将构建整个工程,相当于makefile的功能 - 编译
INSTALL会将生成的dll和exe文件安装到CMAKE_INSTALL_DIR -
ZERO_CHECK会监视CMakeLists.txt,只要后者发生改变就会通知编译器重构工程
- 打开
生成 - 批生成(快捷键Alt+B+T),勾选ALL_BUILD项目的Debug|x64和Release|x64配置,点击生成开始编译。若E:\OSG3.7.0\OpenSceneGraph-master\build\lib中有文件生成则说明编译过程顺利进行,大概2.5小时后完成编译,
批生成选项
生成中
生成完成
-
ALL_BUILD项目编译完成后,再勾选INSTALL项目的Debug|x64和Release|x64配置,点击生成开始编译
INSTALL批生成选项
生成结果
之前编译32位时INSTALL的生成结果
顺利的结果
更新时间为15:20的都是批生成INSTALL后改动过的
OSG环境配置
- 转移数据,编译完成后的文件有11G,实际只需要用到其中一部分。
- 将
E:\OSG\OpenSceneGraph\build的bin、include、lib拷贝到D:\OSG - 将
E:\OSG\Data中的所有内容拷贝到D:\OSG\Data
image.png
- 添加如下环境变量,并重启电脑以使环境变量生效
-
OSG_ROOT:C:\OSG; -
OSG_BIN_PATH:%OSG_ROOT%\bin; -
OSG_INCLUDE_PATH:%OSG_ROOT%\include; -
OSG_LIB_PATH:%OSG_ROOT%\lib; -
OSG_FILE_PATH:%OSG_ROOT%\data; -
PATH:%OSG_BIN_PATH%;
- 打开CMD执行以下命令,以检查是否配置成功
- osgversion // 显示版本号
- osglogo // 出现三维的logo
- osgviewer cow.osg // 出现三维的牛
osgviewer cow.osg
VS环境测试
- 打开VS并新建一个空项目,将Debug调试器设置为
x64
Debug设置为x64
- 右键项目打开
属性,展开配置属性
- 在
VC++ 目录 - 包含目录或C/C++ - 常规 - 附加包含目录中添加$(OSG_INCLUDE_PATH); - 在
VC++ 目录 - 库目录或链接器 - 常规 - 附加库目录中添加$(OSG_LIB_PATH); -
C/C++ - 预处理器 - 预处理器定义设置为WIN32;_WIN32;NDEBUG; -
链接器 - 输入 - 附加依赖项设置为(名称以d结尾代表debug版本,以下文件在C:\OSG\lib中都能找到。kernel32.lib开始是VS2017默认设置的库,只需要添加kernel32.lib之前的lib即可)osgWidgetd.lib;osgVolumed.lib;osgUId.lib;osgTerraind.lib;osgSimd.lib;osgShadowd.lib;osgPresentationd.lib;osgParticled.lib;osgManipulatord.lib;osgFXd.lib;osgAnimationd.lib;OpenThreadsd.lib;osgd.lib;osgDBd.lib;osgUtild.lib;osgGAd.lib;osgViewerd.lib;osgTextd.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
每个lib都有一个debug版本(后缀带d)和release版本
VS设置
- 添加如下源码运行,运行会先弹出一个空的控制台窗口然后显示之前出现过的那头牛
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
int main( int argc, char **argv )
{
osgViewer::Viewer viewer;
viewer.setSceneData( osgDB::readNodeFile( "cow.osg" ) );
return viewer.run();
}
- 样例源码是学习的主要方式,源码在
E:\OSG\OpenSceneGraph\examples中,每个目录是一个示例,其中的cpp文件是源码,如examples\osganimate\osganimate.cpp是两架飞机在一个平面上盘旋飞行
Qt环境测试
- 测试Qt5.10.1运行环境,VS2017安装好
Qt Visual Studio Tools插件后,打开Qt VS Tools-Qt Options配置好Qt的msvc2017_64路径,新建Qt控制台程序
配置Qt路径
新建Qt控制台程序
- 测试之前的源码,配置同之前一样,运行将得到同样的结果
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
int main(int argc, char **argv)
{
osgViewer::Viewer viewer;
viewer.setSceneData(osgDB::readNodeFile("cow.osg"));
return viewer.run();
}
osgQt编译
- 注意:这里使用的是Qt5.10.1版本,进行下列配置出现问题可能是因为版本不同,如使用Qt5.11.0提示
qt5_use_modules命令找不到,原因是Qt5.11.0移除了这个宏。另外的问题可能来源于环境变量,务必检查环境变量的配置,特别是Qt本身的两个环境变量- QTDIR:
C:\Qt\Qt5.10.1\5.10.1\msvc2017_64; - PATH:
%QTDIR%\bin;
- QTDIR:
- 完成OSG的编译与环境变量的配置后,为了能在Qt界面中嵌入osg模型,还需要编译
osgQt,可在此处下载 - 将下载的
osgQt-master.zip移动到E:\OSG并解压
解压后osgQt目录中的文件
- 同样新建一个
build文件夹用于存储编译后的文件
image.png
- 打开
CMakeLists.txt,找到如下两行(130-131行)
FIND_PACKAGE(OpenSceneGraph 3.0.0 REQUIRED osgDB osgGA osgUtil osgText osgViewer osgWidget)
SET(OPENSCENEGRAPH_SOVERSION 145)
CMakeLists.txt
- 修改对应的版本号为3.6.2,157
FIND_PACKAGE(OpenSceneGraph 3.6.2 REQUIRED osgDB osgGA osgUtil osgText osgViewer osgWidget)
SET(OPENSCENEGRAPH_SOVERSION 157)
- 打开
CMake (cmake-gui),将osgQt目录中的CMakeLists.txt拖进去,并把构建目录改为之前新建的build
将CMakeLists.txt拖进cmake
- 点击
Configure,选择Visual Studio 15 2017 Win64
Configure
- 点击
Finish,等待Configuring done
Configuring done
- 修改值
-
BUILD_OSG_EXAMPLES:打勾 -
CMAKE_INSTALL_PREFIX:E:\OSG\osgQt-master\build -
OSG和Qt的设置项会根据环境变量自动检测路径
根据之前搭建的环境配置OSG目录
配置Qt的msvc2017_64的路径
- 再次点击
Configure,窗口中的红色全变为白色
第二次Configure后
- 点击
Generate,生成工程。E:\OSG\osgQt-master\build中将出现生成的osgQt工程,此时可关闭CMake (cmake-gui)
生成的osgQt工程
- 用
VS2017打开osgQt.sln
VS2017打开osgQt项目后的界面
- 打开
生成 - 批生成(快捷键Alt+B+T),勾选ALL_BUILD项目的Debug|x64和Release|x64配置,点击生成开始编译。若E:\OSG\osgQt-master\build\lib中有文件生成则说明编译过程顺利进行,此步花费一分钟即可完成
批生成选项
生成中
生成完成
-
ALL_BUILD项目编译完成后,再勾选INSTALL项目的Debug|x64和Release|x64配置,点击生成开始编译
INSTALL批生成选项
INSTALL生成完成
-
INSTALL编译完成后,在E:\OSG\osgQt\build\share\OpenSceneGraph\bin中将有四个可运行的样例程序
四个可执行样例
-
osgqfont-qt5.exe和osgqfont-qt5d.exe的运行结果是弹出一个窗口,然后显示出字体界面
osgqfont-qt5.exe运行结果
-
osgviewerQt5.exe和osgviewerQt5d.exe的运行结果是弹出一个窗口,然后显示两个窗口界面,左边一个大窗口中有四个区域,分别显示四个模型,右边一个小窗口,显示一辆卡车模型
osgviewerQt5.exe运行结果
osgQt环境配置及测试
- 转移数据:
- 将
E:\OSG\osgQt\build\bin的所有内容拷贝到D:\OSG\bin - 将
E:\OSG\osgQt\build\include\osgQt拷贝到D:\OSG\include - 将
E:\OSG\osgQt\build\lib\pkgconfig\openscenegraph-osgQt5.pc拷贝到D:\OSG\lib\pkgconfig - 将
E:\OSG\osgQt\build\lib的osgQt5.exp、osgQt5.lib、osgQt5d.exp、osgQt5d.lib拷贝到D:\OSG\lib
osgQt的库文件
- 打开VS,新建
Qt GUI Application
新建Qt界面程序
- 必须在向导中勾选
OpenGL,否则后续会出现无法打开包括文件: “QGLWidget”: No such file or directory的错误,原因是后续使用的osgQt/GraphicsWindowQt中有#include <QGLWidget>
勾选OpenGL
osgQt/GraphicsWindowQt
- 项目创建完成,右键项目打开
属性-配置属性
- 在
VC++ 目录 - 包含目录或C/C++ - 常规 - 附加包含目录中添加$(OSG_INCLUDE_PATH); - 在
VC++ 目录 - 库目录或链接器 - 常规 - 附加库目录中添加$(OSG_LIB_PATH); -
链接器 - 输入 - 附加依赖项设置为(这里比之前多了osgQt5d.lib,qtmaind.lib开始是Qt5项目默认设置的库,只需要添加qtmaind.lib之前的lib即可)
osgQt5d.lib;osgWidgetd.lib;osgVolumed.lib;osgUId.lib;osgTerraind.lib;osgSimd.lib;osgShadowd.lib;osgPresentationd.lib;osgParticled.lib;osgManipulatord.lib;osgFXd.lib;osgAnimationd.lib;OpenThreadsd.lib;osgd.lib;osgDBd.lib;osgUtild.lib;osgGAd.lib;osgViewerd.lib;osgTextd.lib;qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5OpenGLd.lib;opengl32.lib;glu32.lib;Qt5Widgetsd.lib;%(AdditionalDependencies)
- 以样例代码作为测试。样例代码在最初解压的
E:\OSG\osgQt\examples中,其中osgqfont和osgviewerQt分别对应之前运行的两个程序。以第二个程序为例,打开E:\OSG\osgQt\examples\osgviewerQt\osgviewerQt.cpp
osgviewerQt.cpp
- 将其内容复制到Qt项目的
main.cpp中
// source file "main.cpp"
#include <QTimer>
#include <QApplication>
#include <QGridLayout>
#include <osgViewer/CompositeViewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/MultiTouchTrackballManipulator>
#include <osgDB/ReadFile>
#include <osgQt/GraphicsWindowQt>
#include <iostream>
class ViewerWidget : public QWidget, public osgViewer::CompositeViewer
{
public:
ViewerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0, osgViewer::ViewerBase::ThreadingModel threadingModel = osgViewer::CompositeViewer::SingleThreaded) : QWidget(parent, f)
{
setThreadingModel(threadingModel);
// disable the default setting of viewer.done() by pressing Escape.
setKeyEventSetsDone(0);
QWidget* widget1 = addViewWidget(createGraphicsWindow(0, 0, 100, 100), osgDB::readRefNodeFile("cow.osgt"));
QWidget* widget2 = addViewWidget(createGraphicsWindow(0, 0, 100, 100), osgDB::readRefNodeFile("glider.osgt"));
QWidget* widget3 = addViewWidget(createGraphicsWindow(0, 0, 100, 100), osgDB::readRefNodeFile("axes.osgt"));
QWidget* widget4 = addViewWidget(createGraphicsWindow(0, 0, 100, 100), osgDB::readRefNodeFile("fountain.osgt"));
QWidget* popupWidget = addViewWidget(createGraphicsWindow(900, 100, 320, 240, "Popup window", true), osgDB::readRefNodeFile("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::ref_ptr<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));
// set the draw and read buffers up for a double buffered window with rendering going to back buffer
camera->setDrawBuffer(GL_BACK);
camera->setReadBuffer(GL_BACK);
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::MultiTouchTrackballManipulator);
gw->setTouchEventsEnabled(true);
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);
#if QT_VERSION >= 0x050000
// Qt5 is currently crashing and reporting "Cannot make QOpenGLContext current in a different thread" when the viewer is run multi-threaded, this is regression from Qt4
osgViewer::ViewerBase::ThreadingModel threadingModel = osgViewer::ViewerBase::SingleThreaded;
#else
osgViewer::ViewerBase::ThreadingModel threadingModel = osgViewer::ViewerBase::CullDrawThreadPerContext;
#endif
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;
#if QT_VERSION >= 0x040800
// Required for multithreaded QGLWidget on Linux/X11, see http://blog.qt.io/blog/2011/06/03/threaded-opengl-in-4-8/
if (threadingModel != osgViewer::ViewerBase::SingleThreaded)
QApplication::setAttribute(Qt::AA_X11InitThreads);
#endif
QApplication app(argc, argv);
ViewerWidget* viewWidget = new ViewerWidget(0, Qt::Widget, threadingModel);
viewWidget->setGeometry(100, 100, 800, 600);
viewWidget->show();
return app.exec();
}
- 运行不再弹出黑窗口,而是直接显示之前
osgviewerQt5d.exe的两个窗口
运行结果