Qt Quick 3D 入门:QML 3D场景详解

随着 Qt 6 的发布,QtQuick3D 模块带来了新的 3D 渲染和交互能力,使得在 Qt 中创建 3D 场景变得更加简单和直观。本文将带您从一个简单的 QML 3D 应用开始,详细讲解各个相关领域的概念、代码实现以及功能特点。

什么是 Qt Quick 3D?

Qt Quick 3D 是 Qt 6 中引入的一个模块,旨在为用户提供便捷的 3D 场景管理和渲染工具。与 Qt 5 中的 Qt 3D 模块相比,QtQuick3D 更加简化,且集成了 Qt Quick 的能力,让 2D 和 3D 内容的结合更加自然。

QML 3D 应用的基本结构

QtQuick3D 中,您可以通过 QML 来定义 3D 场景、物体、灯光、摄像机等。这些内容与 Qt Quick 2D 界面元素可以并存和协作,允许在同一个窗口中同时渲染 2D 和 3D 元素。

以下是我们将要分析的 QML 代码示例,这个例子展示了如何通过 QML 创建一个简单的 3D 场景,并与用户交互。

代码示例程序:

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
{
#if defined(Q_OS_WIN) && QT_VERSION_CHECK(5, 6, 0) <= QT_VERSION && QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/qt/qml/qtquickapplication2/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}
main.qml
import QtQuick.Window
import QtQuick3D
import QtQuick
Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
    View3D {//显示3D的舞台(摄影棚)
        id: _view
        anchors.fill: parent

        environment: SceneEnvironment {//environment设置渲染场景
            //SceneEnvironment为场景的渲染方式定义了一组全局属性。
            clearColor: "red"//环境颜色
            backgroundMode: SceneEnvironment.Color
            antialiasingMode: SceneEnvironment.MSAA
            antialiasingQuality: SceneEnvironment.High
        }
        camera: camera
        PerspectiveCamera {//定义用于查看三维场景内容的透视摄影机(摄像机)。
            id: camera
            position: Qt.vector3d(0, -900, 800)//摄像机位置
            eulerRotation.x: 45//x轴旋转45度
        }

        MouseArea {
            anchors.fill: parent
            onClicked: (mouse)=> {
                let ret = _view.pick(mouse.x, mouse.y)
                if(ret.objectHit !== null)
                    ret.objectHit.materials[0].diffuseColor =
                           Qt.rgba(Math.random(),Math.random(), Math.random(), 1.0)

            }
        }

        DirectionalLight {//场景灯光
           eulerRotation: Qt.vector3d(1, 0, 0)
           castsShadow: true
           brightness: 3
        }

        Model {//物体(拍照对象)
            id: _sphere
            source: "#Sphere"//球
            z: 300
            pickable: true
            scale: Qt.vector3d(2, 2, 2)
            materials: DefaultMaterial {//定义三维材质材质
                diffuseColor: Qt.rgba(0.6, 0.5, 0.2, 1.0)//着色
                 diffuseLightWrap:0//
            }
        }


        Model {
            source: "#Rectangle"
            pickable: true
            scale: Qt.vector3d(10, 10, 1)
            materials: DefaultMaterial {
                diffuseColor: Qt.rgba(0.7, 0.2, 0.2, 1.0)
            }
        }
    }

}

运行结果:

代码分析
1. 创建主窗口

首先,我们需要一个窗口来容纳 3D 内容。这里我们使用 Window 元素,并设置基本的窗口属性,例如宽度、高度和标题。

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
  • Window:定义一个窗口,宽度为 640,高度为 480,并设置标题为“Hello World”。
  • qsTr("Hello World"):Qt 的国际化功能,便于将文本翻译成不同语言。
2. 定义 3D 视图

要显示 3D 内容,首先需要创建一个 View3D,这是 QtQuick3D 中的主要容器,类似于 2D 场景中的 ItemView3D 是一个 3D 场景的承载体,所有 3D 内容都将在这个视图中渲染。

 

qml

View3D {
    id: _view
    anchors.fill: parent
  • View3D:这是一个 3D 视图容器,用于渲染 3D 场景。anchors.fill: parent 将其大小设置为充满整个窗口。
  • id: _view:为 3D 视图定义一个 ID 以便后续引用。
3. 设置场景环境

为了优化 3D 渲染效果,我们可以通过 SceneEnvironment 来设置全局的渲染环境。例如,可以定义背景颜色、抗锯齿模式等。

environment: SceneEnvironment {
    clearColor: "red"
    backgroundMode: SceneEnvironment.Color
    antialiasingMode: SceneEnvironment.MSAA
    antialiasingQuality: SceneEnvironment.High
}

environment: SceneEnvironment { clearColor: "red" backgroundMode: SceneEnvironment.Color antialiasingMode: SceneEnvironment.MSAA antialiasingQuality: SceneEnvironment.High }

  • SceneEnvironment:定义了 3D 场景的渲染环境。
    • clearColor:设置场景背景为红色。
    • backgroundMode:指定背景填充模式为颜色填充。
    • antialiasingModeantialiasingQuality:启用多重采样抗锯齿(MSAA)并设置其质量为高。
4. 添加摄像机

3D 场景的观察依赖于摄像机。PerspectiveCamera 是一种常用的透视摄像机,它能产生与现实世界类似的透视效果。

 
camera: camera
PerspectiveCamera {
    id: camera
    position: Qt.vector3d(0, -900, 800)
    eulerRotation.x: 45
}
  • PerspectiveCamera:定义了一个透视摄像机,用于观察 3D 场景。
    • id: camera:为摄像机设置 ID。
    • position:设置摄像机的位置,x、y 和 z 坐标为(0, -900, 800)。
    • eulerRotation.x: 45:将摄像机绕 X 轴旋转 45 度,使其向下倾斜以获得俯视视角。
5. 添加光照

光照是 3D 渲染中不可或缺的一部分,它决定了物体的明暗和阴影效果。这里使用 DirectionalLight 来模拟来自特定方向的光源。

DirectionalLight {
    eulerRotation: Qt.vector3d(1, 0, 0)
    castsShadow: true
    brightness: 3
}

DirectionalLight { eulerRotation: Qt.vector3d(1, 0, 0) castsShadow: true brightness: 3 }

  • DirectionalLight:定义了场景中的一个方向光源。
    • eulerRotation:设置光源的旋转方向。
    • castsShadow:启用阴影投射效果。
    • brightness:设置光源亮度为 3。
6. 创建 3D 模型

3D 模型是场景中的核心部分。在 QtQuick3D 中,通过 Model 元素定义 3D 物体,并使用 source 属性加载预定义的形状(例如球体、矩形等)。

Model {
    id: _sphere
    source: "#Sphere"
    z: 300
    pickable: true
    scale: Qt.vector3d(2, 2, 2)
    materials: DefaultMaterial {
        diffuseColor: Qt.rgba(0.6, 0.5, 0.2, 1.0)
    }
}
  • Model:创建了一个 3D 模型,源为一个球体(source: "#Sphere")。
    • z: 300:将球体沿 z 轴平移。
    • pickable:模型是可拾取的,也就是说可以用鼠标进行选择和交互。
    • scale:将球体按比例放大 2 倍。
    • materials:指定了球体的材质,diffuseColor 定义了其漫反射颜色为金黄色。

再创建一个矩形模型:

Model {
    source: "#Rectangle"
    pickable: true
    scale: Qt.vector3d(10, 10, 1)
    materials: DefaultMaterial {
        diffuseColor: Qt.rgba(0.7, 0.2, 0.2, 1.0)
    }
}

此模型定义了一个矩形,并设置了红色的材质。

7. 交互:鼠标点击事件

通过 MouseArea,可以捕捉鼠标点击事件,并与 3D 模型进行交互。通过调用 pick 函数,可以检测鼠标点击的模型,并修改其颜色。

MouseArea {
    anchors.fill: parent
    onClicked: (mouse)=> {
        let ret = _view.pick(mouse.x, mouse.y)
        if(ret.objectHit !== null)
            ret.objectHit.materials[0].diffuseColor = Qt.rgba(Math.random(), Math.random(), Math.random(), 1.0)
    }
}
  • MouseArea:定义了一个鼠标区域,覆盖整个 3D 视图。
    • onClicked: 当点击时,调用 _view.pick(mouse.x, mouse.y) 检测点击到的物体,若成功选中物体,则将其材质的漫反射颜色随机改变。
C++ 代码入口

为了启动 QML 应用,我们还需要一个 C++ 程序入口。main.cpp 文件提供了应用程序的启动逻辑,并加载 QML 文件。

#include <QGuiApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
{
#if defined(Q_OS_WIN) && QT_VERSION_CHECK(5, 6, 0) <= QT_VERSION && QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/qt/qml/qtquickapplication2/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}
  • QGuiApplication:负责应用程序的基本设置和生命周期管理。
  • QQmlApplicationEngine:用于加载和执行 QML 文件。在这里,加载了 main.qml,该文件定义了 3D 场景和其所有组件。
  • app.exec():进入应用程序的事件循环,保持应用程序持续运行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/886600.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

关于 JVM 个人 NOTE

目录 1、JVM 的体系结构 2、双亲委派机制 3、堆内存调优 4、关于GC垃圾回收机制 4.1 GC中的复制算法 4.2 GC中的标记清除算法 1、JVM 的体系结构 "堆"中存在垃圾而"栈"中不存在垃圾的原因: 堆(Heap) 用途:堆主要用于存储对象实例和数组。在Java中…

Linux --入门学习笔记

文章目录 Linux概述基础篇Linux 的安装教程 ⇒ 太简单了&#xff0c;百度一搜一大堆。此处略……Linux 的目录结构常用的连接 linux 的开源软件vi 和 vim 编辑器Linux 的关机、开机、重启用户登录和注销用户管理添加用户 ⇒ ( useradd 用户名 ) &#xff08; useradd -d 制定目…

【Unity踩坑】Unity更新Google Play结算库

一、问题描述&#xff1a; 在Google Play上提交了app bundle后&#xff0c;提示如下错误。 我使用的是Unity 2022.01.20f1&#xff0c;看来用的Play结算库版本是4.0 查了一下文档&#xff0c;Google Play结算库的维护周期是两年。现在需要更新到至少6.0。 二、更新过程 1. 下…

Python | Leetcode Python题解之第454题四数相加II

题目&#xff1a; 题解&#xff1a; class Solution:def fourSumCount(self, A: List[int], B: List[int], C: List[int], D: List[int]) -> int:countAB collections.Counter(u v for u in A for v in B)ans 0for u in C:for v in D:if -u - v in countAB:ans countAB…

C++ | Leetcode C++题解之第454题四数相加II

题目&#xff1a; 题解&#xff1a; class Solution { public:int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {unordered_map<int, int> countAB;for (int u: A) {for (int v: B) {count…

Python并发编程(1)——Python并发编程的几种实现方式

更多精彩内容&#xff0c;请关注同名公众&#xff1a;一点sir&#xff08;alittle-sir&#xff09; Python 并发编程是指在 Python 中编写能够同时执行多个任务的程序。并发编程在任何一门语言当中都是比较难的&#xff0c;因为会涉及各种各样的问题&#xff0c;在Python当中也…

C0010.Qt5.15.2下载及安装方法

1. 下载及安装 Qt 添加链接描述下载地址&#xff1a;http://download.qt.io/ 选择 archive 目录 安装Qt **注意&#xff1a;**本人使用的是Qt5.15.2版本&#xff0c;可以按如下方法找到该版本&#xff1b;

Android Studio 新版本 Logcat 的使用详解

点击进入官方Logcat介绍 一个好的Android程序员要会使用AndroidStudio自带的Logcat查看日志&#xff0c;会Log定位也是查找程序bug的第一关键。同时Logcat是一个查看和处理日志消息的工具&#xff0c;它可以更快的帮助开发者调试应用程序。 步入正题&#xff0c;看图说话。 点…

msys2+gdb-multiarch+jlinkGDBServer的nrf52调试环境搭建

前言 刚拿到一块nrf52840的板子&#xff0c;为了方便以后的开发&#xff0c;先搭建一个调试环境&#xff0c;为方便以后回忆记录一下过程。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 1.msys2命令行调用jlink工具 将jlink工具路径加入msys2的PAT…

华为云LTS日志上报至观测云最佳实践

华为云LTS简介 华为云云日志服务&#xff08;Log Tank Service&#xff0c;简称 LTS&#xff09;&#xff0c;用于收集来自主机和云服务的日志数据&#xff0c;通过海量日志数据的分析与处理&#xff0c;可以将云服务和应用程序的可用性和性能最大化&#xff0c;为您提供实时、…

【51单片机】点亮LED之经典流水灯

开发环境 开发板&#xff1a;普中51-单核-A2单片机&#xff1a;STC89C52RC&#xff08;双列直插40引脚 DIP40&#xff09;Keil uVision5 v9.61 最新版破解方法自行百度&#xff0c;相关文档和视频资料很多&#xff0c;我自己将这一操作记录下来当做博客发布&#xff0c;CSDN以…

【数据结构强化】应用题打卡

应用题打卡 数组的应用 对称矩阵的压缩存储 注意&#xff1a; 1. 2.上三角的行优先存储及下三角的列优先存储与数组的下表对应 上/下三角矩阵的压缩存储 注意&#xff1a; 上/下三角压缩存储是将0元素统一压缩存储&#xff0c;而不是将对角线元素统一压缩存储 三对角矩阵的…

King3399 SDK(ubuntu文件系统)编译简明教程

该文章仅供参考&#xff0c;编写人不对任务实验设备、人员及测量结果负责&#xff01;&#xff01;&#xff01; 0 引言 文章主要介绍King3399&#xff08;瑞芯微rk3399开发板&#xff0c;荣品&#xff09;官方SDK&#xff08;Ubuntu文件系统&#xff09;编译过程&#xff0c…

GaussDB关键技术原理:高弹性(六)

书接上文GaussDB关键技术原理&#xff1a;高弹性&#xff08;五&#xff09;从日志多流和事务相关方面对hashbucket扩容技术进行了解读&#xff0c;本篇将从扩容实践方面继续介绍GaussDB高弹性技术。 5 扩容实践 5.1 工具介绍 5.1.1 TPC-C TPC-C(全称Transaction Proces…

Leetcode 540. 有序数组中的单一元素

1.题目基本信息 1.1.题目描述 给你一个仅由整数组成的有序数组&#xff0c;其中每个元素都会出现两次&#xff0c;唯有一个数只会出现一次。 请你找出并返回只出现一次的那个数。 你设计的解决方案必须满足 O(log n) 时间复杂度和 O(1) 空间复杂度。 1.2.题目地址 https:…

[3.4]【机器人运动学MATLAB实战分析】PUMA560机器人逆运动学MATLAB计算

PUMA560是六自由度关节型机器人,其6个关节都是转动副,属于6R型操作臂。各连杆坐标系如图1,连杆参数如表1所示。 图1 PUMA560机器人的各连杆坐标系 表1 PUMA560机器人的连杆参数 用代数法对其进行运动学反解。具体步骤如下: 1、求θ1 PMUMA56

CSS 圆形边框与阴影

目录 1. 圆角边框 1.1 正圆 1.2 圆角矩形 1.3 任意圆角 1.4 某个圆角 2. 盒子阴影 3. 文字阴影 1. 圆角边框 1.1 正圆 1.2 圆角矩形 1.3 任意圆角 1.4 某个圆角 2. 盒子阴影 3. 文字阴影

Vue Mini基于 Vue 3 的小程序框架

新的小程序框架 https://vuemini.org/ Vue Mini 是一个基于 Vue 3 的小程序框架&#xff0c;它允许开发者利用 Vue 3 的强大功能来构建微信小程序。Vue Mini 的核心优势在于它的响应式系统和组合式 API&#xff0c;这些特性让开发者能够以一种更声明式、更高效的方式来编写和…

实景三维赋能城镇数字化规划

在数字化浪潮的推动下&#xff0c;城镇规划正经历着前所未有的变革。实景三维技术以其独特的优势&#xff0c;为城镇数字化规划提供了强大的技术支持。今天&#xff0c;我们将深入探讨实景三维技术如何赋能城镇数字化规划。 一、城镇规划面临的挑战 随着城镇化进程的加快&…

2024年研究生数学建模“华为杯”E题——肘部法则、k-means聚类、目标检测(python)、ARIMA、逻辑回归、混淆矩阵(附:目标检测代码)

文章目录 一、情况介绍二、思路情况二、代码展示三、感受 一、情况介绍 前几天也是参加了研究生数学建模竞赛&#xff08;也就是华为杯&#xff09;&#xff0c;也是和本校的两个数学学院的朋友在网上组的队伍。昨天&#xff08;9.25&#xff09;通宵干完论文&#xff08;一条…