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

Qt Quick 3D-机械臂模型显示与交互

简介

文章目录

  • 简介
  • Quick3D
  • 机械臂模型搭建
  • 代码与演示

Qt Quick 3D 为在QML中创建基于 Qt Quick 的3D内容和3D用户界面提供了一个高级 API。当使用这个空间场景图时,可以将 Qt Quick 的2D内容(Item)与3D内容(Node)混合在一起。

Quick3D

类似与普通组件,Item是2D对象的基类,在3D组件中,Node是3D对象的基类,例如 Camera, Joint, Light,Model等3D相关的组件都继承自NodeNode 本身也可以作为一个"空"的空间节点(用于组织结构)。通常可以以Node为根节点,在其中加入模型,灯光等元素,最后将该节点导入到三维视图窗口组件View3D中进行显示。官方例程可以参考,Qt Quick 3D Examples and Tutorials | Qt Quick 3D | Qt 6.9.3
在这里插入图片描述

机械臂模型搭建

机械臂模型文件来自Robot Arm | Qt 6.9,取其以下文件和文件夹,分别提供了模型描述和模型的网格(mesh)文件。如果要自己搭建模型可以使用相关工具导出,并将模型文件转为mesh,Qt配套的Balsam命令行工具可以将一些常见格式转为View3D支持的mesh格式

查看描述文件层次结构,如下,一个Model套一个Model很像机械臂安装顺序,这样配置内部坐标变换是相对与上一个个父节点(Model)的变换,即相对位置

注意Node只是一个描述组件,并不具有显示功能,还需要创建一个名为View3D的组件,使用其importScene属性,传入Node的id,如下

View3D {  id: view  anchors.fill: parent  importScene: rootNode  camera: came  
}

可以将View3D和Node封装在一个Item下方,这样可供外部调用显示

// Scene3D.qml
Item {Node {id: rootNode  }View3D {anchors.fill: parent  importScene: rootNode }
}// main.qml
Scene3D {
...
}

也可以添加一些组件或者鼠标事件用来控制机械臂之间的相对夹角,或者旋转相机视图或者旋转模型节点,实现交互功能

代码与演示

完整代码如下,注意需要先从官方例程content « robotarm « demos « examples - qt/qtdoc.git - Qt Documentation中找到meshes文件夹放到和该文件同一个目录下,如果安装了Qt,本地电脑应该也有这个例程

import QtQuick  
import QtQuick3D  
import QtQuick.Layouts  
import QtQuick.Controls  Item {  property int rotation1: rotations[0]  property int rotation2: rotations[1]  property int rotation3: rotations[2]  property int rotation4: rotations[3]  property int clawsAngle: rotations[4]  readonly property alias hand_position: hand_grab_t.scenePosition  readonly property alias hand_hinge_position: hand_hinge.scenePosition  readonly property alias arm_position: arm.scenePosition  readonly property alias forearm_position: forearm.scenePosition  readonly property alias root_position: root.scenePosition  property var rotations: [50, 50, 50, 0, 0] // 数组需要重新赋值才能触发绑定更新  property point lastMouse: "0,0"  Behavior on rotation1 {  PropertyAnimation {  duration: 100  }  }  Behavior on rotation2 {  PropertyAnimation {  duration: 100  }  }  Behavior on rotation3 {  PropertyAnimation {  duration: 100  }  }  Behavior on rotation4 {  PropertyAnimation {  duration: 100  }  }  ColumnLayout {  anchors.left: parent.left  anchors.top: parent.top  width: parent.width  Repeater {  id: sliderRepeater  model: [  {label: "Rotation 1", min: -180, max: 180, step: 1, index: 0},  {label: "Rotation 2", min: -180, max: 180, step: 1, index: 1},  {label: "Rotation 3", min: -180, max: 180, step: 1, index: 2},  {label: "Rotation 4", min: -180, max: 180, step: 1, index: 3},  {label: "Claws Angle", min: 0, max: 90, step: 1, index: 4}  ]  delegate: Slider {  Layout.fillWidth: true  Layout.preferredHeight: 40  from: modelData.min  to: modelData.max  stepSize: modelData.step  onValueChanged: {  var newRotations = rotations;  newRotations[modelData.index] = value  rotations = newRotations  // 触发绑定更新  }  }  }  }  Node {  id: rootNode  Node {  PerspectiveCamera {  id: came  // z: 1000  // y: 300                position: Qt.vector3d(0, 100, 400)  eulerRotation.x: 0 // 俯仰角 (Pitch)                eulerRotation.y: 0 // 偏航角 (Yaw)            }  DirectionalLight {  ambientColor: Qt.rgba(0.5, 0.5, 0.5, 1.0)  brightness: 0.8  eulerRotation.x: -25  }  }  Model {  id: base  scale.x: 100  scale.y: 100  scale.z: 100  source: "meshes/base.mesh"  eulerRotation.x: -90  DefaultMaterial {  id: steel_material  diffuseColor: "#ff595959"  }  DefaultMaterial {  id: plastic_material  }  materials: [steel_material, plastic_material]  Model {  id: root  y: -5.96047e-08  z: 1.0472  eulerRotation.z: rotation4  source: "meshes/root.mesh"  DefaultMaterial {  id: plastic_color_material  diffuseColor: "#41cd52"  }  materials: [plastic_material, plastic_color_material, steel_material]  Model {  id: forearm  x: 5.32907e-15  y: -0.165542  z: 1.53472  eulerRotation.x: rotation3  source: "meshes/forearm.mesh"  /* 一个复杂的 3D 模型(如 .glb, .gltf 文件)每个部分称为一个 sub-mesh,可能由多个“部分”组成。 */                    materials: [plastic_material, steel_material]  Model {  id: arm  x: -7.43453e-07  y: 0.667101  z: 2.23365  eulerRotation.x: rotation2  source: "meshes/arm.mesh"  DefaultMaterial {  id: plastic_qt_material  diffuseMap: Texture {  source: "maps/qt.png"  pivotU: 0.5  pivotV: 0.5  generateMipmaps: true  mipFilter: Texture.Linear  }  }  materials: [plastic_material, plastic_qt_material, steel_material]  Model {  id: hand_hinge  x: 7.43453e-07  y: 0.0635689  z: 2.12289  eulerRotation.x: rotation1  source: "meshes/hand_hinge.mesh"  materials: [plastic_material]  Model {  id: hand  x: 3.35649e-06  y: 2.38419e-07  z: 0.366503  source: "meshes/hand.mesh"  materials: [plastic_material, steel_material]  Model {  id: hand_grab_t_hinge_2  x: -9.5112e-07  y: 0.323057  z: 0.472305  eulerRotation: hand_grab_t_hinge_1.eulerRotation  source: "meshes/hand_grab_t_hinge_2.mesh"  materials: [steel_material]  }  Model {  id: hand_grab_t_hinge_1  x: -9.3061e-07  y: 0.143685  z: 0.728553  eulerRotation.x: clawsAngle * -1  source: "meshes/hand_grab_t_hinge_1.mesh"  materials: [steel_material]  Model {  id: hand_grab_t  x: -2.42588e-06  y: -0.0327932  z: 0.414757  eulerRotation.x: hand_grab_t_hinge_1.eulerRotation.x * -1  source: "meshes/hand_grab_t.mesh"  materials: [plastic_color_material, steel_material]  }  }  Model {  id: hand_grab_b_hinge_1  x: -9.38738e-07  y: -0.143685  z: 0.728553  eulerRotation.x: clawsAngle  source: "meshes/hand_grab_b_hinge_1.mesh"  materials: [steel_material]  Model {  id: hand_grab_b  x: -2.41775e-06  y: 0.0327224  z: 0.413965  eulerRotation.x: hand_grab_b_hinge_1.eulerRotation.x * -1  source: "meshes/hand_grab_b.mesh"  materials: [plastic_color_material, steel_material]  }  }  Model {  id: hand_grab_b_hinge_2  x: -9.5112e-07  y: -0.323058  z: 0.472305  eulerRotation: hand_grab_b_hinge_1.eulerRotation  source: "meshes/hand_grab_b_hinge_2.mesh"  materials: [steel_material]  }  }  }  }  }  }  }  }  Item {  anchors.fill: parent  View3D {  id: view  anchors.fill: parent  importScene: rootNode  camera: came  }  MouseArea {  id: cameraControlArea  anchors.bottom: parent.bottom  anchors.left: parent.left  anchors.right: parent.right  height: 200  acceptedButtons: Qt.LeftButton | Qt.RightButton  property real lastMouseX: 0  property real lastMouseY: 0  property var mouse_button: Qt.LeftButton  // 当前按下的鼠标按钮  onPressed: function (mouse) {  // 记录当前位置作为起点  lastMouseX = mouse.x  lastMouseY = mouse.y  mouse_button = mouse.button  }  onPositionChanged: function (mouse) {  if (pressed) {  var deltaX = mouse.x - lastMouseX  var deltaY = mouse.y - lastMouseY  if (mouse_button === Qt.LeftButton) {  base.eulerRotation.y += deltaX  } else if (mouse_button === Qt.RightButton) {  base.position.x += deltaX * 5  base.position.y += -deltaY * 5  }  // 更新上一次鼠标位置  lastMouseX = mouse.x  lastMouseY = mouse.y  }  }  onWheel: function (wheel) {  var delta = wheel.angleDelta.y  came.z += -delta  }  }  }
http://www.dtcms.com/a/445659.html

相关文章:

  • 轻松Linux-10.进程信号
  • 淘宝网站可信度状况及建设策略桂林网站
  • HTML简单入门—— 基础标签与路径解析
  • AI Agent:从“超级玩具“到“核心生产力“,智能新纪元的深度解析
  • 网站开发和运行 法律html5登录界面完整代码
  • 数据预处理与可视化流水线:Pandas Profiling + Altair 实战指南
  • 全栈开发杂谈————关于websocket若干问题的大讨论
  • Headless Service
  • Robotframework7.0与 6.0 的差异
  • dmfldr快速装载工具使用
  • 网站建设技术思维导图wordpress页面结构
  • 兰亭妙微QT软件开发与UI设计协同:如何避免设计与实现脱节?
  • Qt3D--箭头示例
  • 自助建子站龙口网络
  • 【QT常用技术讲解】opencv实现指定分辨率打开摄像头
  • ICT 数字测试原理 7 - -VCL 测试环境
  • stp mode mstp 概念及题目
  • ASP4644芯片低功耗设计思路解析
  • Qt 开发修炼指南:从入门到通透的实战心法
  • 怎么格式化idea中的vue文件
  • MATLAB计算标准化加权平均降水量(Weighted Average Precipitation,SWAP)
  • Leetcode 3702. Longest Subsequence With Non-Zero Bitwise XOR
  • 通辽网站公司福州微信网站建设
  • 网页制作的网站建设wordpress 闪图不
  • 访客申请表添加业主信息字段 - 部署说明
  • Faster RCNN - RPN作用原理
  • 响应式公司网站高端大气公司名称
  • C++之模板进阶:非类型参typename的作用,特化设计与分离编译
  • 树莓派上市后的开源抉择:价格、纯度与生态
  • 顺丰科技java面经准备