在 VS2022 中创建 Qt C++ 项目并配置 OpenSceneGraph 3.6.5
以下是详细的步骤指南,帮助您在 Visual Studio 2022 中创建 Qt C++ 项目并配置 OpenSceneGraph 3.6.5 开发环境:

1. 环境准备
1.1 安装必要软件
-
Visual Studio 2022
- 安装时选择:
- 使用 C++ 的桌面开发
- Windows 10/11 SDK
- C++ CMake 工具
- MSVC v143 - VS 2022 C++ x64/x86 生成工具
- 安装时选择:
-
Qt 6.5.0+ (MSVC 2022 64-bit)
- 从 https://www.qt.io/download 下载在线安装器
- 选择组件:
- Qt 6.5.0 → MSVC 2022 64-bit
- Qt Creator (可选)
- Qt Visual Studio Tools
-
OpenSceneGraph 3.6.5 VC2022 64-bit
- 下载预编译包:
OpenSceneGraph-3.6.5-VC2022-64-2025-04 - 解压到:
C:\OSG\或D:\Development\OSG\
- 下载预编译包:
-
osgQOpenGL 库
- 需要从源码编译或下载预编译版本
2. 配置系统环境变量
2.1 添加环境变量
在系统环境变量中添加:
Path 添加:
C:\Qt\6.5.0\msvc2022_64\bin
C:\OSG\bin
C:\OSG\bin\osgPlugins-3.6.5
新建变量:
OSG_FILE_PATH = C:\OSG\data
QT_DIR = C:\Qt\6.5.0\msvc2022_64
OSG_DIR = C:\OSG
2.2 验证安装
打开命令提示符,运行:
cmd
osgversion
qmake --version
3. 创建 Qt C++ 项目
3.1 方法一:使用 Qt Creator 创建
- 打开 Qt Creator
- 新建项目 → Qt Widgets Application
- 选择工具链:Desktop Qt 6.5.0 MSVC2022 64-bit
- 项目名称:
OSGViewer - 创建完成后,在
.pro文件中添加:
pro
# OSGViewer.pro
QT += core gui opengl
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# 包含目录
INCLUDEPATH += $$(OSG_DIR)/include
INCLUDEPATH += $$(OSG_DIR)/include/osg
INCLUDEPATH += $$(OSG_DIR)/include/osgDB
INCLUDEPATH += $$(OSG_DIR)/include/osgGA
INCLUDEPATH += $$(OSG_DIR)/include/osgViewer
# 库目录
LIBS += -L$$(OSG_DIR)/lib
# 链接库
LIBS += -losgd
LIBS += -losgDBd
LIBS += -losgGAd
LIBS += -losgViewerd
LIBS += -losgUtild
LIBS += -losgTextd
LIBS += -lOpenThreadsd
# 如果是 Release 版本,去掉 'd' 后缀
CONFIG(debug, debug|release) {
# 调试版本
} else {
LIBS += -losg
LIBS += -losgDB
LIBS += -losgGA
LIBS += -losgViewer
LIBS += -losgUtil
LIBS += -losgText
LIBS += -lOpenThreads
}
# 输出目录
DESTDIR = $$OUT_PWD/bin
OBJECTS_DIR = $$OUT_PWD/obj
MOC_DIR = $$OUT_PWD/moc
RCC_DIR = $$OUT_PWD/rcc
UI_DIR = $$OUT_PWD/ui
3.2 方法二:使用 VS2022 创建
- 打开 VS2022
- 创建新项目 → Qt Widgets Application
- 配置项目:
- 项目名称:
OSGViewer - 位置:选择项目文件夹
- 解决方案名称:
OSGViewer - Qt 版本:选择 Qt 6.5.0 MSVC2022 64-bit
- 项目名称:
4. 配置 VS2022 项目属性
4.1 打开项目属性
右键项目 → 属性
4.2 配置包含目录
VC++ 目录 → 包含目录:
$(OSG_DIR)\include
$(OSG_DIR)\include\osg
$(OSG_DIR)\include\osgDB
$(OSG_DIR)\include\osgGA
$(OSG_DIR)\include\osgViewer
$(OSG_DIR)\include\osgUtil
$(OSG_DIR)\include\osgText
$(QT_DIR)\include
4.3 配置库目录
VC++ 目录 → 库目录:
$(OSG_DIR)\lib
$(QT_DIR)\lib
4.4 配置链接器
链接器 → 输入 → 附加依赖项:
Debug 配置:
osgd.lib
osgDBd.lib
osgGAd.lib
osgViewerd.lib
osgUtild.lib
osgTextd.lib
OpenThreadsd.lib
Qt6Cored.lib
Qt6Guid.lib
Qt6Widgetsd.lib
Qt6OpenGLd.lib
Release 配置:
osg.lib
osgDB.lib
osgGA.lib
osgViewer.lib
osgUtil.lib
osgText.lib
OpenThreads.lib
Qt6Core.lib
Qt6Gui.lib
Qt6Widgets.lib
Qt6OpenGL.lib
4.5 配置预处理器定义
C/C++ → 预处理器 → 预处理器定义:
_CRT_SECURE_NO_WARNINGS
_SCL_SECURE_NO_WARNINGS
WIN32
_WINDOWS
UNICODE
_UNICODE
QT_CORE_LIB
QT_GUI_LIB
QT_WIDGETS_LIB
QT_OPENGL_LIB
4.6 配置调试环境
调试 → 环境:
PATH=$(OSG_DIR)\bin;$(QT_DIR)\bin;%PATH%
OSG_FILE_PATH=$(OSG_DIR)\data
5. 创建 OSG 窗口类
5.1 OSGWidget.h
cpp
#pragma once
#include <QOpenGLWidget>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>
#include <osgDB/ReadFile>
#include <osg/Group>
class OSGWidget : public QOpenGLWidget
{
Q_OBJECT
public:
explicit OSGWidget(QWidget* parent = nullptr);
~OSGWidget();
bool loadModel(const QString& filePath);
protected:
virtual void initializeGL() override;
virtual void resizeGL(int w, int h) override;
virtual void paintGL() override;
virtual void mousePressEvent(QMouseEvent* event) override;
virtual void mouseReleaseEvent(QMouseEvent* event) override;
virtual void mouseMoveEvent(QMouseEvent* event) override;
virtual void wheelEvent(QWheelEvent* event) override;
private:
osg::ref_ptr<osgViewer::Viewer> m_viewer;
osg::ref_ptr<osg::Group> m_root;
osg::ref_ptr<osg::Node> m_model;
osg::ref_ptr<osgGA::TrackballManipulator> m_manipulator;
QPoint m_lastMousePos;
};
5.2 OSGWidget.cpp
cpp
#include "OSGWidget.h"
#include <QMouseEvent>
#include <QWheelEvent>
#include <QTimer>
#include <osg/MatrixTransform>
#include <osg/Geode>
#include <osg/ShapeDrawable>
#include <osg/StateSet>
#include <osg/PolygonMode>
OSGWidget::OSGWidget(QWidget* parent)
: QOpenGLWidget(parent)
, m_viewer(new osgViewer::Viewer)
, m_root(new osg::Group)
, m_manipulator(new osgGA::TrackballManipulator)
{
setFocusPolicy(Qt::StrongFocus);
// 设置场景数据
m_viewer->setSceneData(m_root);
// 设置相机操作器
m_viewer->setCameraManipulator(m_manipulator);
// 添加状态事件处理器
m_viewer->addEventHandler(new osgViewer::StatsHandler);
// 设置线程模型
m_viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
// 创建默认场景(一个立方体)
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
osg::ref_ptr<osg::Box> box = new osg::Box(osg::Vec3(0, 0, 0), 1.0f);
osg::ref_ptr<osg::ShapeDrawable> shape = new osg::ShapeDrawable(box);
shape->setColor(osg::Vec4(0.8f, 0.2f, 0.2f, 1.0f));
geode->addDrawable(shape);
// 设置线框模式
osg::ref_ptr<osg::StateSet> stateset = geode->getOrCreateStateSet();
osg::ref_ptr<osg::PolygonMode> pm = new osg::PolygonMode(
osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
stateset->setAttributeAndModes(pm, osg::StateAttribute::ON);
m_root->addChild(geode);
// 设置定时器刷新
QTimer* timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, { update(); });
timer->start(16); // 约60FPS
}
OSGWidget::~OSGWidget()
{
m_viewer->setDone(true);
}
void OSGWidget::initializeGL()
{
// 初始化OpenGL上下文
m_viewer->realize();
// 设置背景色
m_viewer->getCamera()->setClearColor(osg::Vec4(0.1f, 0.1f, 0.1f, 1.0f));
// 设置投影矩阵
m_viewer->getCamera()->setProjectionMatrixAsPerspective(
30.0f, static_cast<double>(width()) / height(), 1.0f, 10000.0f);
}
void OSGWidget::resizeGL(int w, int h)
{
// 更新视口
m_viewer->getCamera()->setViewport(0, 0, w, h);
// 更新投影矩阵
m_viewer->getCamera()->setProjectionMatrixAsPerspective(
30.0f, static_cast<double>(w) / h, 1.0f, 10000.0f);
}
void OSGWidget::paintGL()
{
// 渲染场景
m_viewer->frame();
}
bool OSGWidget::loadModel(const QString& filePath)
{
// 移除旧模型
if (m_model.valid())
{
m_root->removeChild(m_model);
}
// 加载新模型
m_model = osgDB::readNodeFile(filePath.toStdString());
if (!m_model.valid())
{
return false;
}
m_root->addChild(m_model);
// 自动调整视图
osg::BoundingSphere bs = m_model->getBound();
if (bs.valid())
{
m_manipulator->setHomePosition(
bs.center() + osg::Vec3d(0.0, -bs.radius() * 3.0, bs.radius() * 0.5),
bs.center(),
osg::Vec3d(0.0, 0.0, 1.0),
false);
m_manipulator->home(0.0);
}
return true;
}
void OSGWidget::mousePressEvent(QMouseEvent* event)
{
m_lastMousePos = event->pos();
// 处理鼠标事件
if (event->button() == Qt::LeftButton)
{
// 旋转
}
else if (event->button() == Qt::MiddleButton)
{
// 平移
}
else if (event->button() == Qt::RightButton)
{
// 缩放
}
QOpenGLWidget::mousePressEvent(event);
}
void OSGWidget::mouseReleaseEvent(QMouseEvent* event)
{
QOpenGLWidget::mouseReleaseEvent(event);
}
void OSGWidget::mouseMoveEvent(QMouseEvent* event)
{
int dx = event->x() - m_lastMousePos.x();
int dy = event->y() - m_lastMousePos.y();
if (event->buttons() & Qt::LeftButton)
{
// 旋转
m_manipulator->rotate(dx * 0.01, dy * 0.01);
}
else if (event->buttons() & Qt::MiddleButton)
{
// 平移
m_manipulator->pan(dx * 0.01, dy * 0.01);
}
else if (event->buttons() & Qt::RightButton)
{
// 缩放
m_manipulator->zoom(dy * 0.01);
}
m_lastMousePos = event->pos();
update();
QOpenGLWidget::mouseMoveEvent(event);
}
void OSGWidget::wheelEvent(QWheelEvent* event)
{
// 滚轮缩放
QPoint numDegrees = event->angleDelta() / 8;
if (!numDegrees.isNull())
{
m_manipulator->zoom(numDegrees.y() * 0.1);
update();
}
QOpenGLWidget::wheelEvent(event);
}
6. 创建主窗口
6.1 MainWindow.h
cpp
#pragma once
#include <QMainWindow>
#include <QFileDialog>
#include <QMessageBox>
#include "OSGWidget.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget* parent = nullptr);
~MainWindow();
private slots:
void on_actionOpen_triggered();
void on_actionExit_triggered();
void on_actionWireframe_triggered(bool checked);
void on_actionSolid_triggered();
private:
Ui::MainWindow* ui;
OSGWidget* m_osgWidget;
};
6.2 MainWindow.cpp
cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 创建OSG窗口
m_osgWidget = new OSGWidget(this);
setCentralWidget(m_osgWidget);
// 连接菜单信号
connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::on_actionOpen_triggered);
connect(ui->actionExit, &QAction::triggered, this, &MainWindow::on_actionExit_triggered);
connect(ui->actionWireframe, &QAction::toggled, this, &MainWindow::on_actionWireframe_triggered);
connect(ui->actionSolid, &QAction::triggered, this, &MainWindow::on_actionSolid_triggered);
// 设置窗口标题
setWindowTitle("OSG Qt Viewer - 未加载模型");
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionOpen_triggered()
{
QString fileName = QFileDialog::getOpenFileName(
this,
"打开IVE模型文件",
QDir::currentPath(),
"IVE文件 (*.ive);;OSG文件 (*.osg *.osgt *.osgb);;所有文件 (*.*)"
);
if (fileName.isEmpty())
{
return;
}
if (m_osgWidget->loadModel(fileName))
{
setWindowTitle(QString("OSG Qt Viewer - %1").arg(QFileInfo(fileName).fileName()));
statusBar()->showMessage(QString("成功加载: %1").arg(fileName), 3000);
}
else
{
QMessageBox::warning(this, "错误",
QString("无法加载模型文件:\n%1\n请检查文件格式和路径。").arg(fileName));
}
}
void MainWindow::on_actionExit_triggered()
{
close();
}
void MainWindow::on_actionWireframe_triggered(bool checked)
{
// 线框模式切换
// 需要在OSGWidget中添加相应功能
}
void MainWindow::on_actionSolid_triggered()
{
// 实体模式
// 需要在OSGWidget中添加相应功能
}
6.3 MainWindow.ui (Qt Designer 设计)
xml
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>OSG Qt Viewer</string>
</property>
<widget class="QWidget" name="centralwidget"/>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>文件(&F)</string>
</property>
<addaction name="actionOpen"/>
<addaction name="separator"/>
<addaction name="actionExit"/>
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>视图(&V)</string>
</property>
<addaction name="actionWireframe"/>
<addaction name="actionSolid"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuView"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="actionOpen">
<property name="text">
<string>打开模型(&O)</string>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</action>
<action name="actionExit">
<property name="text">
<string>退出(&X)</string>
</property>
<property name="shortcut">
<string>Ctrl+Q</string>
</property>
</action>
<action name="actionWireframe">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>线框模式(&W)</string>
</property>
<property name="shortcut">
<string>F2</string>
</property>
</action>
<action name="actionSolid">
<property name="text">
<string>实体模式(&S)</string>
</property>
<property name="shortcut">
<string>F3</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>
7. 主程序入口
7.1 main.cpp
cpp
#include "MainWindow.h"
#include <QApplication>
#include <QSurfaceFormat>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
// 设置OpenGL格式
QSurfaceFormat format;
format.setRenderableType(QSurfaceFormat::OpenGL);
format.setProfile(QSurfaceFormat::CoreProfile);
format.setVersion(3, 3);
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
format.setSamples(4); // 4x MSAA
QSurfaceFormat::setDefaultFormat(format);
// 设置应用程序信息
app.setApplicationName("OSG Qt Viewer");
app.setOrganizationName("YourCompany");
app.setApplicationVersion("1.0.0");
MainWindow window;
window.show();
return app.exec();
}
8. 编译和运行
8.1 编译步骤
-
生成解决方案
- 在 VS2022 中:生成 → 生成解决方案 (Ctrl+Shift+B)
-
复制 DLL 文件
创建
copy_dlls.bat脚本:batch@echo off set BUILD_DIR=.\x64\Debug set QT_DIR=C:\Qt\6.5.0\msvc2022_64\bin set OSG_DIR=C:\OSG\bin echo 复制Qt DLL文件... copy "%QT_DIR%\Qt6Cored.dll" "%BUILD_DIR%" copy "%QT_DIR%\Qt6Guid.dll" "%BUILD_DIR%" copy "%QT_DIR%\Qt6Widgetsd.dll" "%BUILD_DIR%" copy "%QT_DIR%\Qt6OpenGLd.dll" "%BUILD_DIR%" echo 复制OSG DLL文件... copy "%OSG_DIR%\osgd.dll" "%BUILD_DIR%" copy "%OSG_DIR%\osgDBd.dll" "%BUILD_DIR%" copy "%OSG_DIR%\osgGAd.dll" "%BUILD_DIR%" copy "%OSG_DIR%\osgViewerd.dll" "%BUILD_DIR%" copy "%OSG_DIR%\osgUtild.dll" "%BUILD_DIR%" copy "%OSG_DIR%\osgTextd.dll" "%BUILD_DIR%" copy "%OSG_DIR%\OpenThreadsd.dll" "%BUILD_DIR%" echo 复制插件... xcopy "%OSG_DIR%\osgPlugins-3.6.5" "%BUILD_DIR%\osgPlugins-3.6.5" /E /I /Y echo 完成! pause -
运行程序
- 按 F5 调试运行
- 或直接运行
x64\Debug\OSGViewer.exe
8.2 常见问题解决
问题1:找不到 Qt 库
解决方案:
batch
# 在系统环境变量中添加
Path += C:\Qt\6.5.0\msvc2022_64\bin
问题2:OSG 插件加载失败
解决方案:
cpp
// 在 main.cpp 中添加
#include <osgDB/Registry>
int main(int argc, char* argv[])
{
// 设置插件路径
osgDB::Registry::instance()->setLibraryFilePathList(
"C:/OSG/bin/osgPlugins-3.6.5");
// ...
}
问题3:OpenGL 版本不兼容
解决方案:
cpp
// 在 OSGWidget.cpp 的 initializeGL 中添加
osg::DisplaySettings::instance()->setGLContextVersion("3.3");
osg::DisplaySettings::instance()->setGLContextProfileMask(
osg::DisplaySettings::CORE_PROFILE);
9. 使用 osgQOpenGL 库的替代方案
如果您想使用 osgQOpenGL 库,可以按以下步骤:
9.1 编译 osgQOpenGL
-
下载源码:
bashgit clone https://github.com/openscenegraph/osgQt.git -
使用 CMake 配置:
- 设置 OpenSceneGraph_DIR:
C:/OSG/lib/cmake/OpenSceneGraph - 设置 Qt6_DIR:
C:/Qt/6.5.0/msvc2022_64/lib/cmake/Qt6 - 生成 VS2022 解决方案
- 设置 OpenSceneGraph_DIR:
-
编译并安装
9.2 修改项目配置
在项目属性中添加:
- 包含目录:
C:/OSG/include/osgQOpenGL - 库目录:
C:/OSG/lib - 附加依赖项:
osgQOpenGLd.lib
9.3 修改 OSGWidget
cpp
// 使用 osgQOpenGLWidget
#include <osgQOpenGL/osgQOpenGLWidget>
class OSGWidget : public osgQOpenGLWidget
{
// ...
};
10. 项目结构
OSGViewer/
├── OSGViewer.sln
├── OSGViewer/
│ ├── OSGViewer.vcxproj
│ ├── main.cpp
│ ├── MainWindow.h
│ ├── MainWindow.cpp
│ ├── MainWindow.ui
│ ├── OSGWidget.h
│ └── OSGWidget.cpp
├── x64/
│ └── Debug/
│ ├── OSGViewer.exe
│ ├── *.dll
│ └── osgPlugins-3.6.5/
└── resources/
└── models/
└── example.ive
11. 测试模型
您可以从以下位置获取测试模型:
- OpenSceneGraph 示例数据:
C:\OSG\data - 在线资源:
12. 高级功能扩展
12.1 添加模型列表
cpp
// 在 MainWindow 中添加
QListWidget* m_modelList;
void addModelToList(const QString& filePath);
12.2 添加灯光控制
cpp
// 在 OSGWidget 中添加
osg::ref_ptr<osg::LightSource> m_lightSource;
void setLightEnabled(bool enabled);
void setLightPosition(const osg::Vec3& position);
12.3 添加截图功能
cpp
void OSGWidget::saveScreenshot(const QString& filePath)
{
osg::ref_ptr<osg::Image> image = new osg::Image;
m_viewer->getCamera()->attach(
osg::Camera::COLOR_BUFFER, image.get());
m_viewer->frame();
osgDB::writeImageFile(*image, filePath.toStdString());
}
这个配置指南应该能帮助您在 VS2022 中成功创建和配置 Qt C++ 项目,并使用 OpenSceneGraph 3.6.5 进行三维开发。