资讯动态

VS2017 64位下OSG与Qt环境搭建与OSGQT嵌入实战

发布时间:2026/10/19 12:19:08 来源:尧图企业网站定制
简介这是一份面向Qt与OpenSceneGraphOSG三维渲染开发者的整合示例工程基于Github上广受好评的OSGtree项目整理而来作者在VS2017搭配64位OSG环境下完成调试可直接运行几乎覆盖了OSG与Qt结合所需的各类功能适合有一定C与图形编程基础、希望快速上手三维可视化界面的开发者参考。资源包共72个文件约2.88MB以cpp与h源码为主体配合ui界面文件、qrc资源文件、vcxproj工程文件及pro工程文件另含obj、tlog、pdb等编译中间产物结构完整只需调整环境变量即可复用。目前已有2354人学习下载。工程内包含相机控制、三维视图、树形结构、模型项管理等多个模块读者可借此理解OSG渲染窗口嵌入Qt界面的组织方式、信号槽与场景交互的实现思路并对照现有目录结构快速搭建自己的三维应用框架。1. 从一次编译翻车说起OSG 与 Qt 在 VS2017 下的 64 位环境搭建去年帮一个做三维可视化的朋友处理一个老项目需求很明确把 OSG 的渲染窗口嵌进 Qt 界面里用 VS2017 编译目标平台必须是 64 位。他之前拿到的工程在 32 位下跑得好好的一换到 64 位就各种链接错误折腾了两天没搞定。我接手后发现问题根本不在代码而是 OSG 和 Qt 的库版本、编译选项、运行时库三者没对齐。OSGQT 这个组合本身不复杂但它的坑集中在“位数”和“运行时库”这两个点上一旦错一个报错信息往往指向别处查起来很费时间。这套环境适合需要在 Qt 里做三维场景嵌入的开发者尤其是维护老项目、必须用 VS2017 和 64 位编译的场景。下面把我实际走通的流程拆开讲从环境清单到编译验证每一步都给出可复现的操作。2. 环境清单与版本选择VS2017 下 OSG 和 Qt 的位数对齐2.1 为什么 64 位下最容易翻车的是运行时库VS2017 默认新建项目用的是动态运行时库/MD 或 /MDd而很多预编译的 OSG 库是用静态运行时库/MT 或 /MTd编出来的。32 位下这个问题有时被掩盖因为链接器对符号的容忍度稍高但 64 位下符号修饰规则更严格一旦运行时库不匹配就会出现大量LNK2005重复定义或LNK2019无法解析的外部符号。我一般会先确认三件事OSG 的 lib 文件是用哪个运行时库编的、Qt 的 lib 是动态还是静态、自己的工程设置是否一致。这三者必须统一否则后面怎么改代码都没用。2.2 版本组合与下载来源我这次用的组合是 OSG 3.6.5、Qt 5.12.12、VS2017 15.9。OSG 3.6.5 对 VS2017 的支持比较成熟Qt 5.12 是 LTS 版本和 VS2017 的兼容性经过大量项目验证。下载时注意OSG 要选已经编译好的 64 位二进制包或者自己用 CMake 编Qt 要选msvc2017_64那个套件。如果你拿到的 OSG 包只有 32 位那后面所有工作都是白费所以第一步就是确认位数。组件版本位数获取方式Visual Studio2017 15.964 位官方安装器Qt5.12.12msvc2017_64在线安装器选对应套件OSG3.6.564 位预编译包或 CMake 自编CMake3.2064 位官方安装器2.3 环境变量与目录规划我习惯把第三方库集中放在一个盘符下比如D:\DevLibs下面分osg、qt、cmake三个目录。这样做的目的是让 CMake 和 VS 的路径引用清晰迁移时也方便。设置两个系统环境变量OSG_DIR指向D:\DevLibs\osgQTDIR指向D:\DevLibs\qt\5.12.12\msvc2017_64。然后把%OSG_DIR%\bin和%QTDIR%\bin加到PATH里。这一步不做的话后面运行程序会提示找不到osg165-osg.dll或Qt5Core.dll。# 在系统环境变量里添加不是临时 set OSG_DIR D:\DevLibs\osg QTDIR D:\DevLibs\qt\5.12.12\msvc2017_64 PATH %OSG_DIR%\bin;%QTDIR%\bin;%PATH%提示环境变量改完要重启 VS否则 VS 读到的还是旧值。我见过有人改完直接点编译结果 CMake 找不到 Qt白白浪费半小时。3. 编译 OSGQT 桥接库从 CMake 配置到 VS2017 生成3.1 OSGQT 的角色与源码获取OSGQT 是 OSG 官方提供的一个桥接模块作用是把 OSG 的osgViewer::Viewer嵌入到 Qt 的QWidget里。它本身不是独立库而是 OSG 源码树里的一个子目录src/osgQt。如果你拿到的 OSG 预编译包没有带 osgQt 的 lib那就需要自己从源码编译这个模块。我这次用的是 OSG 3.6.5 的完整源码里面已经包含 osgQt。3.2 CMake 配置的关键参数打开 CMake GUI源码路径指向D:\DevLibs\osg\src\osgQt的上一级也就是 OSG 源码根目录。构建路径新建一个build-osgqt文件夹。点 Configure选择Visual Studio 15 2017 Win64。第一次配置会报错因为找不到 Qt需要手动指定# 在 CMake GUI 里添加以下条目 CMAKE_PREFIX_PATH D:/DevLibs/qt/5.12.12/msvc2017_64 QT_QMAKE_EXECUTABLE D:/DevLibs/qt/5.12.12/msvc2017_64/bin/qmake.exe BUILD_OSG_APPLICATIONS OFF BUILD_OSG_EXAMPLES OFF OSG_BUILD_APPLICATION_BUNDLES OFF这几个参数的含义CMAKE_PREFIX_PATH告诉 CMake 去哪里找 Qt 的配置文件QT_QMAKE_EXECUTABLE直接指定 qmake 路径避免找到系统里其他版本的 Qt后面三个关掉是为了只编译 osgQt 相关目标节省时间。配置成功后在 CMake 里搜索osgQt确认BUILD_OSGQT是勾选状态。3.3 用 VS2017 生成解决方案并编译点 Generate成功后用 VS2017 打开build-osgqt下的OSG.sln。在解决方案里找到osgQt项目右键设为启动项目然后选择Release x64配置。编译前检查一下项目的运行时库设置右键项目 → 属性 → C/C → 代码生成 → 运行库确认是多线程 DLL (/MD)。如果 OSG 主库用的是/MD这里也必须一致。然后生成解决方案等待编译完成。编译成功后在build-osgqt\lib\Release下会得到osgQt.lib和对应的osgQt.dll。# 编译完成后把 osgQt 的头文件和 lib 复制到 OSG 安装目录 copy D:\DevLibs\osg\build-osgqt\lib\Release\osgQt.lib D:\DevLibs\osg\lib\ copy D:\DevLibs\osg\build-osgqt\bin\Release\osgQt.dll D:\DevLibs\osg\bin\ # 头文件在源码的 include\osgQt 下整个目录复制过去 xcopy /E /I D:\DevLibs\osg\src\osgQt\include\osgQt D:\DevLibs\osg\include\osgQt注意复制 dll 时不要漏掉osgQt.dll依赖的其他 OSG dll比如osg165-osg.dll、osg165-osgDB.dll。用 Dependency Walker 或dumpbin /dependents可以查依赖。4. 在 VS2017 里配置 Qt 项目并嵌入 OSG 窗口4.1 创建 Qt 项目并设置 64 位平台在 VS2017 里新建项目选择Qt GUI Application项目名随意。创建向导里会问用哪个 Qt 版本选msvc2017_64。项目建好后第一件事是把平台从x86改成x64在工具栏的解决方案平台下拉框里选x64如果没有就点“配置管理器”新建一个。这一步不做后面链接 64 位 lib 会直接报错。4.2 项目属性里的包含目录和库目录右键项目 → 属性在VC 目录里设置# 包含目录 D:\DevLibs\osg\include D:\DevLibs\qt\5.12.12\msvc2017_64\include # 库目录 D:\DevLibs\osg\lib D:\DevLibs\qt\5.12.12\msvc2017_64\lib然后在链接器 → 输入 → 附加依赖项里加入osgQt.lib osg.lib osgDB.lib osgViewer.lib osgGA.lib Qt5Core.lib Qt5Gui.lib Qt5Widgets.lib Qt5OpenGL.lib这些库的顺序有时会影响链接结果如果出现无法解析的外部符号可以尝试调整顺序把osgQt.lib放在最前面。4.3 嵌入 OSG 窗口的代码实现在 Qt 的主窗口类里添加一个osgQt::GLWidget成员并把它设为中心部件。下面是一个最小可运行的示例// mainwindow.h #include QMainWindow #include osgQt/GraphicsWindowQt #include osgViewer/Viewer #include osgDB/ReadFile class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget* parent nullptr); private: osg::ref_ptrosgViewer::Viewer m_viewer; }; // mainwindow.cpp #include mainwindow.h #include osgQt/GLWidget MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { // 创建 OSG 图形窗口特性 osg::ref_ptrosg::GraphicsContext::Traits traits new osg::GraphicsContext::Traits; traits-x 0; traits-y 0; traits-width 800; traits-height 600; traits-windowDecoration false; traits-doubleBuffer true; traits-sharedContext 0; // 创建 Qt 的 GLWidget内部会创建 GraphicsWindowQt osgQt::GLWidget* glWidget new osgQt::GLWidget(traits.get()); setCentralWidget(glWidget); // 初始化 Viewer 并关联相机 m_viewer new osgViewer::Viewer; m_viewer-setCameraManipulator(new osgGA::TrackballManipulator); m_viewer-setSceneData(osgDB::readNodeFile(cow.osg)); m_viewer-getCamera()-setGraphicsContext(glWidget-getGraphicsWindow()); m_viewer-getCamera()-setViewport(0, 0, 800, 600); m_viewer-realize(); }这段代码的逻辑先构造GraphicsContext::Traits描述窗口属性然后用osgQt::GLWidget创建 Qt 部件它内部会生成GraphicsWindowQt。接着把 Viewer 的相机绑定到这个图形上下文上最后realize()完成初始化。cow.osg是 OSG 自带的示例模型用来验证渲染是否正常。4.4 运行时 dll 的部署编译成功后把osgQt.dll、osg165-osg.dll、osg165-osgDB.dll、osg165-osgViewer.dll、osg165-osgGA.dll以及 Qt 的Qt5Core.dll、Qt5Gui.dll、Qt5Widgets.dll、Qt5OpenGL.dll复制到 exe 同目录。Qt 的插件目录platforms也要复制过去里面至少要有qwindows.dll。这一步漏了程序启动时会报“This application failed to start because no Qt platform plugin could be initialized”。5. 避坑排查OSGQT 在 VS2017 64 位下的五个高频问题5.1 链接错误 LNK2019无法解析的外部符号现象编译时大量LNK2019指向osgQt::GLWidget的构造函数或osgViewer::Viewer的成员函数。原因最常见的是库位数不匹配比如项目是 x64 但链接的osgQt.lib是 32 位的其次是运行时库不一致项目用/MD但 lib 是/MT编的。解决用dumpbin /headers osgQt.lib | findstr machine确认 lib 是 x64在项目属性里把运行库改成和 OSG 库一致通常都是/MD。5.2 程序启动崩溃0xc000007b现象双击 exe 直接报0xc000007b或者提示“应用程序无法正常启动”。原因这个错误码基本就是位数混用比如 exe 是 64 位但某个 dll 是 32 位。解决用 Dependency Walker 打开 exe看哪个 dll 标红。重点检查osgQt.dll、osg165-osg.dll和 Qt 的 dll 是否都是 64 位。Qt 的platforms\qwindows.dll也必须是 64 位版本。5.3 黑屏或白屏窗口创建了但没渲染现象Qt 窗口正常弹出但中间区域是黑的或白的没有三维模型。原因GraphicsWindowQt的上下文没有正确绑定到 Viewer 的相机或者realize()调用时机不对。解决确认m_viewer-getCamera()-setGraphicsContext()传入的是glWidget-getGraphicsWindow()并且setViewport的尺寸和实际窗口一致。如果用了多线程渲染把m_viewer-setThreadingModel(osgViewer::Viewer::SingleThreaded)先改成单线程排查。5.4 找不到 osgQt 头文件现象编译时报Cannot open include file: osgQt/GLWidget。原因osgQt 的头文件没有复制到 OSG 的 include 目录或者项目包含目录里没加D:\DevLibs\osg\include。解决确认D:\DevLibs\osg\include\osgQt\GLWidget这个文件存在。如果不存在从源码的src\osgQt\include\osgQt复制过去。5.5 Qt 插件加载失败现象程序启动时报“no Qt platform plugin could be initialized”。原因exe 同目录下缺少platforms\qwindows.dll或者该 dll 的位数不对。解决从QTDIR\plugins\platforms复制整个platforms文件夹到 exe 目录。如果还不行用QT_DEBUG_PLUGINS1环境变量启动程序看它到底去哪个路径找插件。6. 装完怎么验证三步确认 OSGQT 真的跑通了6.1 用最小场景验证渲染管线不要一上来就跑复杂模型。我一般先用 OSG 自带的cow.osg做验证因为它小、加载快、不需要额外纹理。把cow.osg放在 exe 同目录运行程序后如果能看到一头牛在窗口里并且可以用鼠标拖动旋转说明 OSG 的渲染管线、Qt 的窗口嵌入、相机交互这三条链路都通了。如果牛出不来先检查osgDB::readNodeFile的返回值是不是空可以在代码里加一行if (!node) return;来确认文件是否加载成功。6.2 检查 dll 依赖是否干净在 exe 目录下打开命令行运行dumpbin /dependents YourApp.exe看输出的 dll 列表里有没有带路径的、或者指向System32下 32 位版本的。重点确认osgQt.dll、osg165-osg.dll、Qt5Core.dll都在同目录并且用dumpbin /headers查一下它们的 machine 字段都是x64。这一步能提前发现大部分“在我机器上能跑”的问题。6.3 用 Release 和 Debug 分别跑一遍很多人只测 Release结果 Debug 下崩溃。原因是 Debug 版链接的库不同运行时库是/MDd而 OSG 预编译包通常只有 Release 版。如果必须在 Debug 下调试要么自己用/MDd重新编译 OSG要么在 Debug 项目里把运行库改成/MD并链接 Release 版的 OSG lib。我一般会在项目里建两个配置Release|x64用/MD链接 Release 库Debug|x64也链接 Release 库但开启调试信息这样能避开/MDd缺失的问题。# 验证时用到的检查命令汇总 dumpbin /headers D:\DevLibs\osg\bin\osgQt.dll | findstr machine dumpbin /dependents YourApp.exe # 设置 Qt 插件调试 set QT_DEBUG_PLUGINS1 YourApp.exe从那以后我每次配 OSGQT 环境都强制先跑一遍dumpbin /headers确认所有 lib 和 dll 的 machine 字段是 x64再开始写代码。这个习惯帮我省掉了至少三次重装系统的冲动。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑