OSG3.7.0+VS2017编译
2019-02-13 本文已影响0人
downdemo
编译OSG3.7.0
- 编译过程参考Compiling with Visual Studio,需要的安装包可在osgChina或OSG官网获取。以下是此次编译过程中所用的工具版本及其下载地址:
- 源码包:OpenSceneGraph-3.7.0
- 第三方库依赖:VS2017全部依赖64位
- 数据包:OpenSceneGraph-Data-3.4.0.zip
- CMeke:cmake-3.13.3-win64-x64.msi
- VS2017社区版
- 新建
E:\OSG3.7.0
,下载上述前三个压缩包并解压到此目录
- 在
E:\OSG3.7.0\OpenSceneGraph-master
新建一个build
文件夹用于存放编译内容
- 安装
cmake-3.13.3-win64-x64.msi
,安装完成后重启电脑,否则Configure时可能出现error in configuration process project files may be invalid
的错误
- 打开
CMake (cmake-gui)
,将E:\OSG3.7.0\OpenSceneGraph-master\CMakeLists.txt
拖到CMake (cmake-gui)
中(或者手动输入路径),并将构建路径改为新建的E:\OSG3.7.0\OpenSceneGraph-master\build
- 点击
Configure
,为了生成64位版本,选择Visual Studio 15 2017 Win64
并点击Finish
。注意,若此处选择Visual Studio 15 2017
则将生成32位版本
- 等待大概二十秒完成Configure,将出现一批红色选项
- Configure完成后修改如下几个选项,可用Search功能快速找到对应选项
-
ACTUAL_3RDPARTY_DIR
:E:/OSG3.7.0/3rdParty_x64
-
BUILD_OSG_EXAMPLES
:打勾 -
CMAKE_INSTALL_PREFIX
:E:/OSG3.7.0/OpenSceneGraph-master/build
- 第二次点击
Configure
,界面选项仍为红色 - 第三次点击
Configure
,完成后界面将没有红色选项
- 点击
Generate
,Generate完成后将在E:\OSG3.7.0\OpenSceneGraph-master\build
中生成工程文件,此时即可关闭cmake-gui
- 用VS2017打开
E:\OSG3.7.0\OpenSceneGraph-master\build\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小时后完成编译,提示========== 生成: 成功 542 个,失败 0 个,最新 0 个,跳过 0 个 ==========
-
ALL_BUILD
项目编译完成后,再勾选INSTALL
项目的Debug|x64
和Release|x64
配置,点击生成
开始编译
- 此步会将所需要的文件复制到
E:\OSG3.7.0\OpenSceneGraph-master\build
的cmake
、include
、share
、lib
中,share
中是样例程序。此步一分钟即可完成,提示========== 生成: 成功 2 个,失败 0 个,最新 542 个,跳过 0 个 ==========
,编译完成后,编译信息将保存在E:\OSG3.7.0\OpenSceneGraph-master\build\install_manifest.txt
中
转移数据
- 编译完成后的文件有大概12G,而实际只需要用到其中一部分:
- 新建
C:\OSG
文件夹 - 将
E:\OSG3.7.0\OpenSceneGraph-master\build
的bin
、include
、lib
复制到C:\OSG
- 将
E:\OSG3.7.0\OpenSceneGraph-Data
拷贝到C:\OSG
,并改名为data
- 添加如下环境变量,并重启电脑以使环境变量生效
-
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 // 出现三维的牛
VS环境测试
- 打开VS并新建一个空项目,将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)
- 添加如下源码运行,运行会先弹出一个空的控制台窗口然后显示之前出现过的那头牛
#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:\OSG3.7.0\OpenSceneGraph-master\examples
中,如examples\osganimate\osganimate.cpp
是两架飞机在一个平面上盘旋飞行的源码
osgQt编译
- 注意:这里使用的是Qt5.10.1版本,进行下列配置出现问题可能是因为版本不同,如使用Qt5.11.0提示
qt5_use_modules
命令找不到,原因是Qt5.11.0移除了这个宏。另外的问题可能来源于环境变量,务必检查环境变量的配置,特别是Qt本身的两个环境变量-
QT5_DIR
:C:\Qt\Qt5.10.1\5.10.1\msvc2017_64;
-
PATH
:%QT5_DIR%\bin;
-
- 完成OSG的编译与环境变量的配置后,为了能在Qt界面中嵌入osg模型,还需要编译
osgQt
,可在此处下载 - 将下载的
osgQt-master.zip
移动到E:\OSG3.7.0
并解压,并同样新建一个E:\OSG3.7.0\osgQt-master\build
文件夹用于存储编译后的文件 - 打开
CMakeLists.txt
,找到如下两行(130-131行)
FIND_PACKAGE(OpenSceneGraph 3.0.0 REQUIRED osgDB osgGA osgUtil osgText osgViewer osgWidget)
SET(OPENSCENEGRAPH_SOVERSION 145)
- 修改对应的版本号为3.7.0,160
FIND_PACKAGE(OpenSceneGraph 3.7.0 REQUIRED osgDB osgGA osgUtil osgText osgViewer osgWidget)
SET(OPENSCENEGRAPH_SOVERSION 160)
- 打开
CMake (cmake-gui)
,将E:\OSG3.7.0\osgQt-master\CMakeLists.txt
拖进去,并把构建目录改为之前新建的build
- 点击
Configure
,选择Visual Studio 15 2017 Win64
,点击Finish
,等待几秒后Configuring done
- 修改值
-
BUILD_OSG_EXAMPLES
:打勾 -
CMAKE_INSTALL_PREFIX
:E:\OSG\osgQt-master\build
- OSG和Qt的设置项会根据环境变量自动检测路径
Qt5Core_DIR
:C:/Qt/Qt5.10.1/5.10.1/msvc2017_64/lib/cmake/Qt5Core
Qt5Gui_DIR
:C:/Qt/Qt5.10.1/5.10.1/msvc2017_64/lib/cmake/Qt5Gui
Qt5Network_DIR
:C:/Qt/Qt5.10.1/5.10.1/msvc2017_64/lib/cmake/Qt5Network
Qt5OpenGL_DIR
:C:/Qt/Qt5.10.1/5.10.1/msvc2017_64/lib/cmake/Qt5OpenGL
Qt5WebKitWidgets_DIR
:C:/Qt/Qt5.10.1/5.10.1/msvc2017_64/lib/cmake/Qt5WebKitWidgets
Qt5WebKit_DIR
:C:/Qt/Qt5.10.1/5.10.1/msvc2017_64/lib/cmake/Qt5WebKit
Qt5Widgets_DIR
:C:/Qt/Qt5.10.1/5.10.1/msvc2017_64/lib/cmake/Qt5Widgets
Qt5_DIR
:C:/Qt/Qt5.10.1/5.10.1/msvc2017_64/lib/cmake/Qt5
配置Qt的msvc2017_64的路径
- 再次点击
Configure
,窗口中的红色全变为白色 - 点击
Generate
,生成工程。E:\OSG3.7.0\osgQt-master\build
中将出现生成的osgQt
工程,此时可关闭CMake (cmake-gui)
- 用
VS2017
打开osgQt.sln
- 打开
生成 - 批生成(快捷键Alt+B+T)
,勾选ALL_BUILD
项目的Debug|x64
和Release|x64
配置,点击生成
开始编译。若E:\OSG3.7.0\osgQt-master\build\lib
中有文件生成则说明编译过程顺利进行,此步花费一分钟即可完成 -
ALL_BUILD
项目编译完成后,再勾选INSTALL
项目的Debug|x64
和Release|x64
配置,点击生成
开始编译 -
INSTALL
编译完成后,在E:\OSG3.7.0\osgQt-master\share\OpenSceneGraph\bin
中将有四个可运行的样例程序 -
osgqfont-qt5.exe
和osgqfont-qt5d.exe
的运行结果是弹出一个窗口,然后显示出字体界面 -
osgviewerQt5.exe
和osgviewerQt5d.exe
的运行结果是弹出一个窗口,然后显示两个窗口界面,左边一个大窗口中有四个区域,分别显示四个模型,右边一个小窗口,显示一辆卡车模型
osgQt环境配置及测试
- 转移数据:
- 将
E:\OSG3.7.0\osgQt-master\build\bin
的所有内容拷贝到C:\OSG\bin
- 将
E:\OSG3.7.0\osgQt-master\build\osgQt
拷贝到C:\OSG\include
- 将
E:\OSG3.7.0\osgQt-master\build\lib\pkgconfig\openscenegraph-osgQt5.pc
拷贝到C:\OSG\lib\pkgconfig
- 将
E:\OSG3.7.0\osgQt-master\build\lib
的osgQt5.exp、osgQt5.lib、osgQt5d.exp、osgQt5d.lib
拷贝到C:\OSG\lib
- 打开VS,新建
Qt GUI Application
- 必须在向导中勾选
OpenGL
,否则后续会出现无法打开包括文件: “QGLWidget”: No such file or directory
的错误,原因是后续使用的osgQt/GraphicsWindowQt
中有#include <QGLWidget>
- 项目创建完成,右键项目打开
属性-配置属性
- 在
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:\OSG3.7.0\osgQt-master\examples
中,其中osgqfont
和osgviewerQt
分别对应之前运行的两个程序。以第二个程序为例,打开E:\OSG3.7.0\osgQt-master\examples\osgviewerQt\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
的两个窗口