简介:这是一份面向OSG与Qt联合开发初学者及中级开发者的可运行示例工程,源自GitHub上较受认可的OSGTree项目,作者在VS2017搭配64位OSG环境下完成调试,解压后仅需调整环境变量即可直接编译运行,可用于学习三维渲染窗口与Qt界面框架的集成方式。压缩包共72个文件,约2.88MB,以cpp与h源码为主体,配合ui界面文件、qrc资源文件、vcxproj工程文件及pro工程文件,另含obj、tlog、pdb等编译中间产物,覆盖相机控制、三维视图、树形结构、模型加载等典型模块,几乎囊括OSG与Qt结合所需的常见功能点。目前已有2354人学习下载,适合需要参考完整工程结构、对照调试思路或快速搭建OSG+Qt开发环境的读者,可从中获取界面与渲染逻辑的衔接方式、工程配置要点及模块划分参考。
1. OSGQT 结合的例子 VS2017+64位完美运行:先别急着编译,把版本对齐再说
如果你在 Windows 上做三维可视化,大概率绕不开 OSG 和 Qt 的组合。OSG 负责渲染,Qt 负责界面,听起来分工明确,但真正动手把两者拼到一起,很多人第一步就卡住了——不是编译报错,就是运行闪退,再不然就是窗口嵌进去了但鼠标事件完全没反应。我见过太多人在这上面耗掉一整天,最后发现只是版本位数没对齐。VS2017 配 64 位环境本身没问题,问题出在 OSG 预编译包、Qt 安装包和编译器三者之间的位数必须完全一致。这份 OSGQT 结合的例子就是针对 VS2017 加 64 位环境整理的,适合正在搭三维可视化框架、需要把 OSG 渲染窗口嵌入 Qt 界面的开发者。装之前先把版本关系理清楚,后面能省掉大量返工。
2. 环境准备:VS2017、Qt 和 OSG 的版本怎么选
2.1 三个组件的位数必须一致
这是最容易翻车的地方。VS2017 本身有 32 位和 64 位编译器,Qt 官方安装包分 32 位和 64 位两套,OSG 的预编译包也分 32 位和 64 位。三者只要有一个位数不匹配,链接阶段就会报一堆LNK2019或LNK2038错误。我一般会先确认三件事:VS2017 安装时勾选了“使用 C++ 的桌面开发”并且包含 64 位工具集;Qt 安装的是msvc2017_64版本;OSG 用的是 VS2017 对应的 64 位预编译包。如果 OSG 只有源码,那就得自己用 CMake 配 VS2017 的 64 位生成器编译一遍,这一步后面会讲。
提示:Qt 的
msvc2017_64和msvc2019_64不能混用,即使都是 64 位,ABI 也不兼容。
2.2 版本对照表
| 组件 | 推荐版本 | 位数 | 备注 |
|---|---|---|---|
| Visual Studio | 2017 (15.x) | 64 位工具集 | 需安装 C++ 桌面开发工作负载 |
| Qt | 5.12.x 或 5.9.x | msvc2017_64 | 5.12 是长期支持版,兼容性较好 |
| OSG | 3.4.0 或 3.6.x | 64 位 | 优先选带 VS2017 预编译的包 |
| CMake | 3.10 以上 | 64 位 | 仅在需要自行编译 OSG 时使用 |
Qt 版本不要盲目追新,5.12 之后的版本对 VS2017 的支持虽然还在,但某些模块的编译参数有变化,容易在链接 OSG 时出问题。OSG 3.4.0 是比较稳的选择,3.6.x 对 C++11 要求更高,如果项目里还有其他老库,可能会冲突。
2.3 环境变量与路径规划
安装路径尽量短,不要带空格和中文。我习惯把 Qt 装在C:\Qt,OSG 放在C:\OSG,VS2017 默认路径不动。装完之后需要把 OSG 的bin目录加到系统PATH里,否则运行时会提示找不到osg.dll或osgQt.dll。Qt 的bin目录也要加,不然Qt5Core.dll同样找不到。这两个路径加完最好重启一次终端或者刷新环境变量,否则 VS2017 里调试时可能读不到。
# 以管理员身份打开 cmd,临时验证 PATH 是否生效 echo %PATH% # 确认输出里包含 C:\OSG\bin 和 C:\Qt\5.12.12\msvc2017_64\bin如果不想改系统 PATH,也可以在 VS2017 的项目属性里把这两个目录加到“调试环境”中,但那样只对当前项目有效,换项目还得重配。我一般直接改系统变量,一劳永逸。
3. 安装与配置:从 OSG 编译到 Qt 项目集成
3.1 OSG 预编译包的使用与验证
如果你拿到的是 OSG 预编译包,解压后应该能看到include、lib、bin三个目录。bin里是动态库,lib里是导入库,include是头文件。先验证 OSG 本身能不能跑起来,打开 cmd 执行:
osgversion # 正常输出类似:OpenSceneGraph Library 3.4.0如果提示不是内部或外部命令,说明bin目录没加到 PATH。这一步过了再往下走,否则后面 Qt 集成时出的错你分不清是 OSG 的问题还是 Qt 的问题。
3.2 用 CMake 编译 OSG(没有预编译包时)
没有现成 64 位包的情况下,用 CMake 自己编。打开 CMake GUI,源码路径指向 OSG 源码根目录,构建路径新建一个build-vs2017-64文件夹。点击 Configure,选择Visual Studio 15 2017 Win64生成器。第一次配置会报一些可选依赖找不到,比如PNG、JPEG、TIFF,这些不影响核心功能,可以先忽略。关键选项是BUILD_OSG_APPLICATIONS和DYNAMIC_OSG,前者决定要不要编译示例程序,后者决定生成动态库还是静态库。我一般保持动态库,方便后续替换。
# CMake 配置完成后,在 build 目录执行编译 cmake --build . --config Release --target INSTALL # INSTALL 目标会把头文件、库和可执行文件复制到 CMAKE_INSTALL_PREFIX 指定的目录编译过程大概十几分钟,取决于机器性能。完成后把安装目录下的bin加到 PATH,再用osgversion验证一遍。
3.3 Qt 项目的 .pro 文件配置
Qt 项目用.pro管理依赖时,需要把 OSG 的头文件路径和库路径写进去。下面是一个最小可用的配置片段:
# OSG 头文件路径 INCLUDEPATH += C:/OSG/include # OSG 库路径 LIBS += -LC:/OSG/lib # 链接核心库和 Qt 集成库 LIBS += -losg -losgViewer -losgDB -losgQt # Qt 模块 QT += core gui widgets opengl-losgQt是 OSG 提供的 Qt 集成库,负责把osgViewer::Viewer嵌入到QWidget中。如果链接时提示找不到osgQt,检查 OSG 编译时是否开启了BUILD_OSG_QT选项,有些预编译包默认不带这个库。
3.4 在 Qt Designer 中嵌入 OSG 窗口
纯代码方式嵌入 OSG 窗口比较直接,继承QWidget并重写paintEvent,在构造函数里创建osgViewer::Viewer并设置QWidget为图形窗口句柄。关键代码结构如下:
// 自定义 OsgWidget 继承 QWidget OsgWidget::OsgWidget(QWidget* parent) : QWidget(parent) { // 创建 viewer viewer = new osgViewer::Viewer; // 设置 Qt 窗口句柄 osgQt::GraphicsWindowQt* gw = new osgQt::GraphicsWindowQt(this->geometry()); viewer->getCamera()->setGraphicsContext(gw); viewer->setCameraManipulator(new osgGA::TrackballManipulator); // 设置渲染窗口 viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded); }GraphicsWindowQt是 osgQt 库里的关键类,它把 Qt 的QWidget和 OSG 的图形上下文桥接起来。setThreadingModel建议用SingleThreaded,多线程模式下 Qt 事件循环和 OSG 渲染循环容易打架,导致界面卡死。
4. 避坑排查:OSGQT 集成中最常见的五个问题
4.1 编译报 LNK2038:RuntimeLibrary 不匹配
现象是链接阶段报LNK2038: 检测到“RuntimeLibrary”的不匹配项。原因是 OSG 库和 Qt 库使用的运行时库不一致,比如一个是MD一个是MT。解决方法是统一项目属性里的“C/C++ → 代码生成 → 运行时库”,全部设为多线程 DLL (/MD)。如果 OSG 预编译包用的是MT,那就得重新编译 OSG 或者换包。
4.2 运行闪退:osgQt.dll 找不到
程序编译通过但一运行就退出,事件查看器里能看到模块加载失败。原因是osgQt.dll不在可执行文件目录或 PATH 里。把 OSG 的bin目录加到 PATH,或者直接把需要的 dll 复制到 exe 同级目录。我一般用Dependencies工具扫一遍 exe,看缺哪个补哪个。
4.3 窗口嵌入后鼠标事件无响应
OSG 窗口显示正常但鼠标拖拽旋转没反应。原因是GraphicsWindowQt没有正确接收鼠标事件,需要在自定义QWidget里把mousePressEvent、mouseMoveEvent等转发给GraphicsWindowQt。另一个可能是TrackballManipulator没设置,检查setCameraManipulator是否调用。
4.4 高分辨率屏幕下渲染模糊
在 4K 屏上 OSG 渲染区域模糊,原因是 Qt 的高 DPI 缩放和 OSG 的视口尺寸没同步。解决方法是在main函数里设置QApplication::setAttribute(Qt::AA_EnableHighDpiScaling),然后在GraphicsWindowQt创建时用devicePixelRatio调整实际渲染尺寸。
4.5 编译 OSG 时 CMake 找不到 Qt
自己编译 OSG 时 CMake 报Could NOT find Qt5。原因是CMAKE_PREFIX_PATH没指向 Qt 安装目录。在 CMake GUI 里手动添加CMAKE_PREFIX_PATH为C:/Qt/5.12.12/msvc2017_64,重新 Configure 即可。如果还是找不到,检查 Qt 安装时是否勾选了msvc2017_64组件。
5. 验证跑通:用最小示例确认 OSGQT 环境可用
装完之后别急着往项目里塞代码,先跑一个最小示例确认环境没问题。新建一个 Qt Widgets Application,在main.cpp里创建一个QWidget,嵌入osgViewer::Viewer,加载一个简单的osg::Node,比如一个立方体或者 OSG 自带的cow.osg。如果窗口能显示模型并且鼠标可以旋转缩放,说明 OSG、Qt、VS2017 三者已经打通。
// main.cpp 最小验证代码 #include <QApplication> #include <osgViewer/Viewer> #include <osgDB/ReadFile> #include <osgQt/GraphicsWindowQt> int main(int argc, char** argv) { QApplication app(argc, argv); // 创建 Qt 图形窗口 osg::ref_ptr<osgQt::GraphicsWindowQt> gw = new osgQt::GraphicsWindowQt(new QWidget); // 创建 viewer 并绑定图形上下文 osgViewer::Viewer viewer; viewer.getCamera()->setGraphicsContext(gw); viewer.getCamera()->setViewport(0, 0, 800, 600); // 加载模型 viewer.setSceneData(osgDB::readNodeFile("cow.osg")); // 设置操作器 viewer.setCameraManipulator(new osgGA::TrackballManipulator); // 显示窗口并进入事件循环 gw->getWidget()->show(); return app.exec(); }这段代码的关键点是GraphicsWindowQt的构造参数,传入一个QWidget作为父窗口,然后viewer.getCamera()->setGraphicsContext(gw)把 OSG 的渲染上下文绑定到 Qt 窗口上。setViewport的参数是像素值,如果窗口大小会变化,需要在resizeEvent里动态调整。cow.osg是 OSG 自带的示例模型,在OSG_DATA目录下能找到,如果没有就去 OSG 源码的data目录里复制一个。
跑通之后,再逐步把项目里的相机操作、场景图加载、事件处理加进去。每加一个功能就验证一次,不要一次性全堆上去,否则出问题很难定位是哪个环节引入的。从那以后我每次配新环境都强制走一遍这个最小示例,确认基础链路通了再动业务代码。希望帮到你。
本文还有配套的精品资源,点击获取