QT(c++)开发自学笔记:4.Qt 3D简易实现

一、一个简单的例子

显示鼠标可以拖动的3D正方体

CMakeLists.txt完整代码如下:

bash 复制代码
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.cpp
    dialog.cpp
    dialog.h
    dialog.ui
)

# 链接 Qt 模块
target_link_libraries(${PROJECT_NAME} PRIVATE
    Qt6::Core
    Qt6::Gui
    Qt6::Widgets
    Qt6::3DCore
    Qt6::3DRender
    Qt6::3DInput
    Qt6::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 的核心功能(如 QObjectQString)。
    • Gui:GUI 相关功能(如 QColorQWidget)。
    • Widgets:Widget 系统(如 QDialogQVBoxLayout)。
    • 3DCore:Qt 3D 核心模块(如 QEntityQTransform)。
    • 3DRender:Qt 3D 渲染模块(如 QCameraQMaterial)。
    • 3DInput:Qt 3D 输入模块(如 QOrbitCameraController 的输入处理)。
    • 3DExtras:Qt 3D 扩展模块(如 QCuboidMeshQPhongMaterialQOrbitCameraController)。
      • 项目使用 Qt3DExtras::Qt3DWindowQt3DCore::QEntityQt3DExtras::QCuboidMeshQt3DExtras::QPhongMaterial 等,依赖 3DCore3DRender3DExtras
      • QOrbitCameraController 需要 3DInput3DExtras
      • QDialogQVBoxLayout 需要 Widgets
      • QColor 需要 Gui

add_executable(${PROJECT_NAME} main.cpp dialog.cpp dialog.h dialog.ui )

  • 作用 :定义可执行目标 My3DCube,包含源文件 main.cppdialog.cppdialog.h 和 UI 文件 dialog.ui
    • main.cpp 启动应用程序,通常创建 QApplicationDialog 实例。
    • dialog.cppdialog.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 功能,确保 QPhongMaterialQCuboidMeshQOrbitCameraController 等类的可用性。

include(GNUInstallDirs) install(TARGETS ${PROJECT_NAME} BUNDLE DESTINATION . RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )

  • 作用
    • include(GNUInstallDirs):定义标准安装路径(如 binlib)。
    • install:指定安装规则,将可执行文件安装到 CMAKE_INSTALL_BINDIR(通常为 bin 目录)。

dialog.h代码如下:

cpp 复制代码
#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_NAMESPACE

class Dialog : public QDialog
{
    Q_OBJECT

public:
    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如下:

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如下:

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模型显示范围,可以适当拉大一点

运行结果如下:

相关推荐
wan5555cn4 小时前
中国启用WPS格式进行国际交流:政策分析与影响评估
数据库·人工智能·笔记·深度学习·算法·wps
半夏知半秋6 小时前
redis-哨兵模式配置整理
数据库·redis·笔记·后端·学习·lua·安全架构
草莓熊Lotso6 小时前
模板进阶:从非类型参数到分离编译,吃透 C++ 泛型编程的核心逻辑
linux·服务器·开发语言·c++·人工智能·笔记·后端
ouliten9 小时前
cuda编程笔记(33)--Thrust库的使用
笔记·cuda
摇滚侠14 小时前
Spring Boot 3零基础教程,新特性 ProblemDetails,笔记50
spring boot·笔记
一只一只14 小时前
Unity 3D笔记(进阶部分)——《B站阿发你好》
笔记·3d·unity·游戏引擎
月临水15 小时前
Git 学习笔记
笔记·git·学习·1024程序员节
朝新_16 小时前
【SpringBoot】详解Maven的操作与配置
java·spring boot·笔记·后端·spring·maven·javaee
-Excalibur-18 小时前
形象解释关于TCP/IP模型——层层封装MAC数据帧的过程
linux·c语言·网络·笔记·单片机·网络协议·tcp/ip