当前位置: 首页 > news >正文

Qt Quick 3D 基础与应用

Qt Quick 3D 是 Qt 框架中用于创建 3D 内容的模块,它允许开发者在 QML 环境中轻松集成 3D 元素,与 2D UI 组件无缝协作。无论是简单的 3D 模型展示还是复杂的交互式 3D 场景,Qt Quick 3D 都提供了直观且高效的开发方式。本文将深入解析 Qt Quick 3D 的核心概念和应用技术。

一、Qt Quick 3D 基础组件

1. 基本 3D 场景结构
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick3D 1.15Window {id: mainWindowvisible: truewidth: 800height: 600title: "Qt Quick 3D 基础场景"// 3D 视图容器View3D {id: view3danchors.fill: parent// 3D 场景根节点Scene {id: scene// 相机PerspectiveCamera {id: cameraposition: Qt.vector3d(0, 0, 10)  // 相机位置 (x, y, z)eulerRotation: Qt.vector3d(0, 0, 0)  // 相机旋转fieldOfView: 60  // 视场角}// 光源DirectionalLight {id: dirLighteulerRotation: Qt.vector3d(45, 45, 0)  // 光源方向color: Qt.rgba(1, 1, 0.9, 1)  // 暖白色光intensity: 1.0  // 光强度}// 3D 模型 - 内置立方体Model {id: cubesource: "#Cube"  // 使用内置几何体position: Qt.vector3d(0, 0, 0)  // 模型位置// 材质materials: [DefaultMaterial {id: cubeMaterialdiffuseColor: "#4a90e2"  // 漫反射颜色}]// 旋转动画NumberAnimation on eulerRotation.y {from: 0to: 360duration: 5000loops: Animation.Infinite}}// 地面Model {id: groundsource: "#Plane"  // 平面几何体position: Qt.vector3d(0, -2, 0)scale: Qt.vector3d(5, 1, 5)  // 缩放平面materials: [DefaultMaterial {diffuseColor: "#f0f0f0"}]}}}
}
2. 核心组件解析
  • View3D: 3D 渲染的容器,负责将 3D 场景绘制到屏幕上
  • Scene: 3D 场景的根节点,所有 3D 元素的父容器
  • Camera: 定义观察视角,支持透视相机(PerspectiveCamera)和正交相机(OrthographicCamera)
  • Light: 提供场景照明,包括方向光、点光源、聚光灯等
  • Model: 3D 模型容器,可加载内置几何体或外部模型文件
  • Material: 定义模型表面的视觉属性,如颜色、纹理、光泽度等

二、3D 几何体与模型

1. 内置几何体

Qt Quick 3D 提供多种内置基础几何体:

// 内置几何体示例
Row {spacing: 20anchors.centerIn: parentView3D {width: 150height: 150Scene {PerspectiveCamera { position: Qt.vector3d(0, 0, 5) }DirectionalLight { eulerRotation: Qt.vector3d(45, 45, 0) }Model {source: "#Cube"  // 立方体materials: [DefaultMaterial { diffuseColor: "red" }]}}}View3D {width: 150height: 150Scene {PerspectiveCamera { position: Qt.vector3d(0, 0, 5) }DirectionalLight { eulerRotation: Qt.vector3d(45, 45, 0) }Model {source: "#Sphere"  // 球体materials: [DefaultMaterial { diffuseColor: "green" }]}}}View3D {width: 150height: 150Scene {PerspectiveCamera { position: Qt.vector3d(0, 0, 5) }DirectionalLight { eulerRotation: Qt.vector3d(45, 45, 0) }Model {source: "#Cylinder"  // 圆柱体materials: [DefaultMaterial { diffuseColor: "blue" }]}}}
}
2. 加载外部 3D 模型

Qt Quick 3D 支持加载多种格式的外部模型:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick3D 1.15Window {width: 800height: 600visible: truetitle: "加载外部 3D 模型"View3D {anchors.fill: parentScene {PerspectiveCamera {position: Qt.vector3d(0, 5, 15)eulerRotation: Qt.vector3d(20, 0, 0)}DirectionalLight {eulerRotation: Qt.vector3d(45, 45, 0)intensity: 1.2}// 加载 glTF 格式模型Model {id: importedModelsource: "models/car.glb"  // glTF 二进制格式position: Qt.vector3d(0, 0, 0)scale: Qt.vector3d(0.5, 0.5, 0.5)  // 缩放模型// 模型加载状态监控onStatusChanged: {if (status === Model.Ready) {console.log("模型加载完成")} else if (status === Model.Error) {console.log("模型加载错误:", errorString)}}// 自动旋转NumberAnimation on eulerRotation.y {from: 0to: 360duration: 20000loops: Animation.Infinite}}// 地面Model {source: "#Plane"position: Qt.vector3d(0, -1, 0)scale: Qt.vector3d(10, 1, 10)materials: [DefaultMaterial {diffuseColor: "#e0e0e0"}]}}}
}

支持的模型格式包括:glTF 2.0 (.gltf, .glb)、Wavefront OBJ (.obj)、STL (.stl) 等。

三、材质与纹理

1. 基础材质属性
Model {source: "#Sphere"position: Qt.vector3d(0, 0, 0)scale: Qt.vector3d(2, 2, 2)materials: [DefaultMaterial {// 漫反射颜色diffuseColor: "#4a90e2"// 金属度 (0-1)metallic: 0.8// 粗糙度 (0-1)roughness: 0.3// 环境光遮蔽ambientOcclusion: 0.5// 自发光emissiveColor: "#1a1a33"emissiveIntensity: 0.5}]
}
2. 纹理映射
Model {source: "#Cube"position: Qt.vector3d(0, 0, 0)materials: [DefaultMaterial {// 漫反射纹理diffuseMap: Texture {source: "textures/wood_diffuse.jpg"magnificationFilter: Texture.LinearminificationFilter: Texture.LinearMipMapLinear}// 法线纹理 (增加表面细节)normalMap: Texture {source: "textures/wood_normal.jpg"normalScaling: Qt.vector2d(0.5, 0.5)}// 粗糙度纹理roughnessMap: Texture {source: "textures/wood_roughness.jpg"}// 金属度纹理metallicMap: Texture {source: "textures/wood_metallic.jpg"}}]
}

四、相机与视角控制

1. 多相机切换
View3D {anchors.fill: parentcamera: activeCamera  // 使用当前激活的相机property Camera activeCamera: camera1Scene {// 相机 1: 正面视角PerspectiveCamera {id: camera1position: Qt.vector3d(0, 0, 10)}// 相机 2: 顶部视角PerspectiveCamera {id: camera2position: Qt.vector3d(0, 10, 0)eulerRotation: Qt.vector3d(90, 0, 0)}// 相机 3: 侧面视角PerspectiveCamera {id: camera3position: Qt.vector3d(10, 0, 0)eulerRotation: Qt.vector3d(0, 90, 0)}// 3D 物体Model {source: "#TorusKnot"materials: [DefaultMaterial { diffuseColor: "purple" }]}DirectionalLight { eulerRotation: Qt.vector3d(45, 45, 0) }}
}// 相机切换按钮
Row {anchors.bottom: parent.bottomanchors.horizontalCenter: parent.horizontalCenteranchors.bottomMargin: 20spacing: 10Button {text: "正面"onClicked: view3d.activeCamera = view3d.scene.camera1}Button {text: "顶部"onClicked: view3d.activeCamera = view3d.scene.camera2}Button {text: "侧面"onClicked: view3d.activeCamera = view3d.scene.camera3}
}
2. 鼠标控制相机
View3D {id: view3danchors.fill: parentScene {PerspectiveCamera {id: cameraposition: Qt.vector3d(0, 5, 10)eulerRotation: Qt.vector3d(20, 0, 0)// 相机控制属性property real orbitSpeed: 0.5property real zoomSpeed: 0.1property real panSpeed: 0.02}DirectionalLight { eulerRotation: Qt.vector3d(45, 45, 0) }Model {source: "#Suzanne"  // 猴子头模型materials: [DefaultMaterial { diffuseColor: "#ff6b6b" }]}Model {source: "#Plane"position: Qt.vector3d(0, -2, 0)scale: Qt.vector3d(10, 1, 10)materials: [DefaultMaterial { diffuseColor: "#f0f0f0" }]}}// 鼠标控制相机MouseArea {anchors.fill: parentdrag.active: pressedwheel.enabled: trueproperty var lastMousePosonPressed: {lastMousePos = Qt.point(mouseX, mouseY)}onMouseXChanged: {if (pressed) {// 左右拖动 - 旋转相机环绕物体var delta = mouseX - lastMousePos.xcamera.eulerRotation.y += delta * camera.orbitSpeedlastMousePos.x = mouseX}}onMouseYChanged: {if (pressed) {// 上下拖动 - 旋转相机仰角var delta = mouseY - lastMousePos.yvar newPitch = camera.eulerRotation.x - delta * camera.orbitSpeed// 限制仰角范围if (newPitch > -89 && newPitch < 89) {camera.eulerRotation.x = newPitch}lastMousePos.y = mouseY}}onWheel: {// 鼠标滚轮 - 缩放var delta = wheel.angleDelta.yvar newZ = camera.position.z - delta * camera.zoomSpeed// 限制缩放范围if (newZ > 3 && newZ < 20) {camera.position.z = newZ}}}
}

五、3D 动画与交互

1. 模型动画
Model {id: animatedModelsource: "models/character.glb"  // 包含骨骼动画的模型// 动画控制器AnimationController {id: animControlleranimation: animatedModel.animations[0]  // 使用第一个动画running: trueloops: Animation.Infinite}// 动画切换function playAnimation(index) {if (index >= 0 && index < animatedModel.animations.length) {animController.animation = animatedModel.animations[index]animController.restart()}}
}// 动画控制按钮
Row {spacing: 10anchors.bottom: parent.bottomanchors.horizontalCenter: parent.horizontalCenterButton {text: "走路"onClicked: animatedModel.playAnimation(0)}Button {text: "跑步"onClicked: animatedModel.playAnimation(1)}Button {text: "跳跃"onClicked: animatedModel.playAnimation(2)}
}
2. 3D 物体拾取
View3D {id: view3danchors.fill: parentScene {id: scenePerspectiveCamera {id: cameraposition: Qt.vector3d(0, 5, 10)eulerRotation: Qt.vector3d(20, 0, 0)}DirectionalLight { eulerRotation: Qt.vector3d(45, 45, 0) }// 可点击的 3D 物体Repeater {model: 5delegate: Model {id: clickableModelsource: "#Sphere"position: Qt.vector3d((index - 2) * 2, 0, 0)scale: Qt.vector3d(0.8, 0.8, 0.8)materials: [DefaultMaterial {id: matdiffuseColor: isSelected ? "red" : "blue"}]property bool isSelected: false// 3D 拾取器Picker {id: pickeronPressed: {// 重置其他物体for (var i = 0; i < scene.children.length; i++) {var child = scene.children[i];if (child !== picker && child.isSelected !== undefined) {child.isSelected = false;}}// 选中当前物体clickableModel.isSelected = true;}}}}}// 鼠标区域用于拾取MouseArea {anchors.fill: parentonClicked: {// 从点击位置发射射线检测碰撞var pickResult = view3d.pick(mouseX, mouseY);if (pickResult) {console.log("选中物体:", pickResult.object.name);}}}
}

六、2D 与 3D 混合界面

Qt Quick 3D 允许 2D UI 元素与 3D 场景无缝融合:

import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick3D 1.15
import QtQuick.Controls 2.15Window {width: 1024height: 768visible: truetitle: "2D 与 3D 混合界面"// 3D 场景作为背景View3D {anchors.fill: parentScene {PerspectiveCamera {position: Qt.vector3d(0, 5, 15)eulerRotation: Qt.vector3d(20, 0, 0)}DirectionalLight { eulerRotation: Qt.vector3d(45, 45, 0) }Model {source: "#Sphere"materials: [DefaultMaterial { diffuseColor: "#4a90e2" }]NumberAnimation on eulerRotation.y {from: 0to: 360duration: 10000loops: Animation.Infinite}}Model {source: "#Plane"position: Qt.vector3d(0, -2, 0)scale: Qt.vector3d(10, 1, 10)materials: [DefaultMaterial { diffuseColor: "#f0f0f0" }]}}}// 2D UI 元素覆盖在 3D 场景上Rectangle {id: topBaranchors.top: parent.topanchors.left: parent.leftanchors.right: parent.rightheight: 50color: "rgba(0, 0, 0, 0.7)"Text {anchors.centerIn: parentcolor: "white"font.pointSize: 16text: "3D 模型查看器"}}Column {anchors.left: parent.leftanchors.top: topBar.bottomanchors.bottom: parent.bottomspacing: 10padding: 10Button {text: "旋转"onClicked: {// 控制 3D 模型var sphere = view3d.scene.children[2];  // 获取球体模型if (sphere) {sphere.eulerRotation.x += 90;}}}Button {text: "重置"onClicked: {var sphere = view3d.scene.children[2];if (sphere) {sphere.eulerRotation = Qt.vector3d(0, 0, 0);}}}Slider {id: scaleSliderwidth: 100from: 0.5to: 2.0value: 1.0onValueChanged: {var sphere = view3d.scene.children[2];if (sphere) {sphere.scale = Qt.vector3d(value, value, value);}}}}// 信息面板Rectangle {anchors.right: parent.rightanchors.bottom: parent.bottomwidth: 200height: 150color: "rgba(255, 255, 255, 0.8)"radius: 5padding: 10Column {spacing: 5Text {text: "模型信息"font.bold: true}Text {text: "类型: 球体"}Text {text: "缩放: " + scaleSlider.value.toFixed(1) + "x"}}}
}

七、总结

Qt Quick 3D 为开发者提供了在 QML 环境中创建和集成 3D 内容的强大能力:

  1. 核心组件:通过 View3D、Scene、Camera、Light 和 Model 构建基础 3D 场景
  2. 模型处理:支持内置几何体和外部模型文件加载
  3. 材质系统:提供丰富的材质属性和纹理映射能力
  4. 相机控制:支持多视角切换和交互控制
  5. 动画与交互:实现模型动画、相机控制和 3D 物体拾取
  6. 混合界面:无缝整合 2D UI 元素与 3D 场景

Qt Quick 3D 特别适合需要在应用中添加 3D 元素但不需要复杂 3D 引擎功能的场景,如产品展示、数据可视化、教育应用等。其与 QML 的深度集成使得开发者能够利用现有的 Qt Quick 知识快速构建富 3D 体验的应用程序。

http://www.dtcms.com/a/309138.html

相关文章:

  • 【数据结构初阶】--排序(一):直接插入排序,希尔排序
  • zabbix平台无法删除已停用主机的处理案例
  • 基于springboot的快递分拣管理系统
  • 信号发生器和示波器阻抗匹配问题
  • 重生之我在暑假学习微服务第七天《微服务之服务治理篇》
  • flutter设备图标颜色与字体颜色相同自动适配明与暗的模式
  • 力扣 hot100 Day62
  • UnityURP 使用StencilBuffer制作一个“看见看不见”的球
  • 第三方采购流程
  • 前端图片懒加载的深度指南:从理论到实战
  • 使用 whisper, 音频分割, 初步尝试,切割为小块,效果还不错 1
  • java对象的内存分配
  • linux编译基础知识-工具链
  • datagrip连接mysql数据库过程以及遇到的问题
  • Linux网络:多路转接 epoll
  • 深入讲讲异步FIFO
  • Blender 4.5 安装指南:快速配置中文版,适用于Win/mac/Linux系统
  • 汽车EDI:Vitesco EDI 项目案例
  • 基于单片机汽车少儿安全预警系统
  • 【世纪龙科技】汽车整车维护仿真教学软件-智构整车维护实训
  • Oracle EBS ERP开发 — 抛出异常EXCEPTION书写规范
  • 【世纪龙科技】3D交互深度赋能-汽车整车维护仿真教学软件
  • Baumer工业相机堡盟工业相机如何通过YoloV8深度学习模型实现道路汽车的检测识别(C#代码,UI界面版)
  • Apache RocketMQ for AI 战略升级,开启 AI MQ 新时代
  • GXP6040K压力传感器可应用于医疗/汽车/家电
  • 在SQL SERVER 中,用SSMS 实现存储过程的每日自动调用
  • 嵌入式系统教学范式演进:云端仿真平台如何重构温湿度监测实验教学
  • Web开发-PHP应用弱类型脆弱Hash加密Bool类型Array数组函数转换比较
  • 动态规划 Dynamic programming
  • 渗透作业3