QT(c++)开发自学笔记:4.Qt 3D简易实现
一、一个简单的例子
显示鼠标可以拖动的3D正方体
CMakeLists.txt完整代码如下:
cmake_minimum_required(VERSION 3.16)project(My3DCube LANGUAGES CXX)set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)# 自动运行 moc、uic、rcc
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)# 查找 Qt6 组件(必须包含 3D 相关模块)
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets 3DCore 3DRender 3DInput 3DExtras)# 添加可执行文件
add_executable(${PROJECT_NAME}main.cppdialog.cppdialog.hdialog.ui
)# 链接 Qt 模块
target_link_libraries(${PROJECT_NAME} PRIVATEQt6::CoreQt6::GuiQt6::WidgetsQt6::3DCoreQt6::3DRenderQt6::3DInputQt6::3DExtras
)# 可选:安装规则
include(GNUInstallDirs)
install(TARGETS ${PROJECT_NAME}BUNDLE DESTINATION .RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
逐行分析如下:
cmake_minimum_required(VERSION 3.16)
作用:指定 CMake 的最低版本要求为 3.16,确保构建系统支持所需的 CMake 功能。足以支持 Qt 6 和 Qt 3D 的构建需求。
project(My3DCube LANGUAGES CXX)
- 作用:定义项目名称为
My3DCube,指定使用 C++ 语言。
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON)
- 作用:设置 C++ 标准为 C++17,并要求强制使用该标准。
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON)
- 作用:
CMAKE_AUTOMOC:启用 Qt 的元对象编译器(moc),自动处理包含Q_OBJECT宏的头文件(如dialog.h)。CMAKE_AUTOUIC:自动处理 Qt Designer 生成的.ui文件(如dialog.ui),将其转换为 C++ 代码。CMAKE_AUTORCC:自动处理 Qt 资源文件(.qrc),但当前项目未使用资源文件。dialog.ui需要CMAKE_AUTOUIC来生成 UI 代码。dialog.h包含Q_OBJECT宏(因为Dialog继承QDialog),需要CMAKE_AUTOMOC。- 当前没有
.qrc文件,CMAKE_AUTORCC可保留以支持未来扩展。
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets 3DCore 3DRender 3DInput 3DExtras)
- 作用:查找 Qt6 库,并要求包含以下模块:
Core:Qt 的核心功能(如QObject、QString)。Gui:GUI 相关功能(如QColor、QWidget)。Widgets:Widget 系统(如QDialog、QVBoxLayout)。3DCore:Qt 3D 核心模块(如QEntity、QTransform)。3DRender:Qt 3D 渲染模块(如QCamera、QMaterial)。3DInput:Qt 3D 输入模块(如QOrbitCameraController的输入处理)。3DExtras:Qt 3D 扩展模块(如QCuboidMesh、QPhongMaterial、QOrbitCameraController)。- 项目使用
Qt3DExtras::Qt3DWindow、Qt3DCore::QEntity、Qt3DExtras::QCuboidMesh、Qt3DExtras::QPhongMaterial等,依赖3DCore、3DRender和3DExtras。 QOrbitCameraController需要3DInput和3DExtras。QDialog和QVBoxLayout需要Widgets。QColor需要Gui。
- 项目使用
add_executable(${PROJECT_NAME} main.cpp dialog.cpp dialog.h dialog.ui )
- 作用:定义可执行目标
My3DCube,包含源文件main.cpp、dialog.cpp、dialog.h和 UI 文件dialog.ui。main.cpp启动应用程序,通常创建QApplication和Dialog实例。dialog.cpp和dialog.h实现 3D 场景逻辑(立方体、相机、背景色等)。dialog.ui定义 UI 布局(包含qt3dContainer用于嵌入Qt3DWindow)。- 文件列表完整,符合项目结构。
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets Qt6::3DCore Qt6::3DRender Qt6::3DInput Qt6::3DExtras )
- 作用:将可执行目标
My3DCube链接到 Qt6 的指定模块,确保程序能访问所需库。 - 链接的模块与
find_package一致,涵盖了所有 Qt 3D 和 Widget 功能,确保QPhongMaterial、QCuboidMesh、QOrbitCameraController等类的可用性。
include(GNUInstallDirs) install(TARGETS ${PROJECT_NAME} BUNDLE DESTINATION . RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )
- 作用:
include(GNUInstallDirs):定义标准安装路径(如bin、lib)。install:指定安装规则,将可执行文件安装到CMAKE_INSTALL_BINDIR(通常为bin目录)。
dialog.h代码如下:
#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <Qt3DExtras/Qt3DWindow>
#include <Qt3DCore/QEntity>
#include <Qt3DCore/QTransform>
#include <Qt3DExtras/QCuboidMesh>
#include <Qt3DExtras/QPhongMaterial>
#include <Qt3DInput/QMouseHandler>
#include <QOrbitCameraController>
#include <Qt3DRender/QFrameGraphNode> // 支持 frame graph 相关类
#include <Qt3DExtras/QForwardRenderer> // 显式包含 QForwardRenderer
#include <QVBoxLayout> // 支持布局操作QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACEclass Dialog : public QDialog
{Q_OBJECTpublic:explicit Dialog(QWidget *parent = nullptr);~Dialog();private:Ui::Dialog *ui;Qt3DExtras::Qt3DWindow *m_view;QWidget *m_container;Qt3DCore::QEntity *m_rootEntity;Qt3DCore::QEntity *m_cubeEntity;void setup3DScene();
};#endif // DIALOG_H
dialog.cpp如下:
#include "dialog.h"
#include "ui_dialog.h"#include <Qt3DExtras/QOrbitCameraController>
#include <Qt3DRender/QCamera>
#include <Qt3DCore/QTransform>Dialog::Dialog(QWidget *parent) :QDialog(parent),ui(new Ui::Dialog),m_view(nullptr),m_container(nullptr),m_rootEntity(nullptr),m_cubeEntity(nullptr)
{ui->setupUi(this);// 创建 Qt3D 窗口m_view = new Qt3DExtras::Qt3DWindow();// 修改背景色为白色m_view->defaultFrameGraph()->setClearColor(QColor("#FFFFFF"));// 创建容器 widget 并嵌入到 UI 中m_container = QWidget::createWindowContainer(m_view, ui->qt3dContainer);// 检查 qt3dContainer 是否有布局,如果没有则添加一个if (!ui->qt3dContainer->layout()) {QVBoxLayout *layout = new QVBoxLayout(ui->qt3dContainer);layout->addWidget(m_container);} else {ui->qt3dContainer->layout()->addWidget(m_container);}setup3DScene();
}Dialog::~Dialog()
{delete ui;
}void Dialog::setup3DScene()
{// 根实体m_rootEntity = new Qt3DCore::QEntity();// === 创建正方体 ===m_cubeEntity = new Qt3DCore::QEntity(m_rootEntity);// 几何体:正方体auto *cubeMesh = new Qt3DExtras::QCuboidMesh();cubeMesh->setXExtent(2.0f);cubeMesh->setYExtent(2.0f);cubeMesh->setZExtent(2.0f);// 材质:浅蓝色auto *material = new Qt3DExtras::QPhongMaterial();material->setDiffuse(QColor("#6495ED")); // 浅蓝色(Cornflower Blue)material->setAmbient(QColor("#6495ED")); // 设置环境光为相同浅蓝色,确保无光源时可见// 不设置高光(specular)和光泽(shininess),因为没有光源// 变换:初始位置和旋转auto *transform = new Qt3DCore::QTransform();transform->setScale(1.0f);transform->setTranslation(QVector3D(0.0f, 0.0f, 0.0f));// 添加组件m_cubeEntity->addComponent(cubeMesh);m_cubeEntity->addComponent(material);m_cubeEntity->addComponent(transform);// === 相机 ===auto *camera = m_view->camera();camera->lens()->setPerspectiveProjection(45.0f, 16.0f / 9.0f, 0.1f, 1000.0f);camera->setPosition(QVector3D(0, 0, 10.0f));camera->setViewCenter(QVector3D(0, 0, 0));// === 轨道相机控制器(支持鼠标拖动旋转、滚轮缩放)===auto *camController = new Qt3DExtras::QOrbitCameraController(m_rootEntity);camController->setLinearSpeed(50.0f);camController->setLookSpeed(180.0f);camController->setCamera(camera);// 设置根实体m_view->setRootEntity(m_rootEntity);
}
main.cpp如下:
#include <QApplication>
#include "dialog.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);Dialog w;w.setWindowTitle("3D 正方体 - 鼠标拖动旋转");w.resize(800, 600);w.show();return a.exec();
}
dailog.ui中只需要拖入一个Widget框,然后给它命名为qt3dContainer就行,这个框就是3D模型显示范围,可以适当拉大一点

运行结果如下:

