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

【qml-12】Quick3D达成机器人鼠标拖拽转换视角(无限角度)与滚轮缩放

背景:

还是这个机器人示教器项目,上一篇说到使用WasdController实现的拖拽视角,并不是很完美。此篇记录的是:

可以使用鼠标拖拽,实现视角的无限切换,无论物体现在什么姿态,只管任意拖拽鼠标,直到想要的姿态为止。

可以使用鼠标滚轮缩放物体大小。

可以一键重置。

WasdController:

之所以说这种方式不好,是基于我最初的需求而言。如果想拖拽鼠标转换视角,那它就有bug。

因为WasdController的功能,实际是控制目标节点的相对姿态,假设目标节点是个有生命虫子,它原本的姿态是跟屏幕前的你一样,面朝屏幕深处,背朝屏幕(也就是你),上下左右跟屏幕前的你一样。

所以想象一下,如果是个3d游戏,极品飞车那种室外视角,屏幕里那个车的姿态。使用WasdController时,在屏幕上拖拽上下左右,车头就会随动。

(图片源于网络,如有侵权请告知)

再想象如果让WasdController控制相机,用鼠标在屏幕上拖动上下左右时,很像极品飞车的车内视角,或者cs这类第一视角的游戏画面效果。

(图片源于网络,如有侵权请告知)

(图片源于网络,如有侵权请告知)

而且WasdController还可以支持键盘操作。所以实际上如果你用quick做个3d游戏,真的可以。

只是对于我最初的需求而言不太合适。所以就有了下面新的方法。

在这之前还是要强调一句,非常推荐先做demo,把可能的各种数值做成可以在界面调整的,范围大一些。方便调试。想象一下,只旋转镜头(camera)的话,等于自己扭头,很可能看不见目标物体,所以要调整参数,才知道具体什么效果。

MouseArea:

其实最早想到的就是用这个了,只不过刚好看到WasdController,就想着尽量简单去实现,无奈它不能胜任,所以下面看如何用MouseArea实现。

先回顾一下我曾做过的一个简单版的预览调试界面:

左边滑块按照从上往下说。

1、横向:实际是调整的机器人节点的z轴欧拉旋转,也就是说,无论总体场景的姿态如何,只要左右拖动,机器人即自己左右转。

2、纵向:实际是机器人父级节点的x轴欧拉旋转。

3、camera xyz:很少用,也就一开始用一下看看效果。镜头上下远近动,物体就动(上下左右正好相反)。

4、上条中,本次使用的就是camera的z,控制远近,也就是大小(近大远小)。

5、后面就是机器人关节控制,本次不说了。

最上面的复位:让1、2归零,以及下文实现的机器人相关参数归零。

下面以代码为例说明。

RobotArea.qml:

只取部分节选。

    //定义属性,用于外界输入参数property double _dAngleHorizontal: 0property double _dAngleVertical: 0//让外界知道鼠标拖拽的幅度readonly property double _dX_AngleDraged: _ma._dX_AngleDragedreadonly property double _dY_AngleDraged: _ma._dY_AngleDraged//让外界调用,用于重置姿态function f_ResetPosture(){_ma._rX_prev = 0;_ma._rY_prev = 0;_ma._dX_draged = 0;_ma._dY_draged = 0;_ma._dX_AngleDraged = 0;_ma._dY_AngleDraged = 0;}//让外界知道滚轮变化数值,实际对应相机z轴数值,也就是远近property double _dScale: 0//之前的WasdController不用了// WasdController {//     controlledObject: scene//     xSpeed: -0.1//     ySpeed: -0.1// }MouseArea {id: _maanchors.fill: parentproperty real _rX_prev: 0property real _rY_prev: 0property double _dX_draged: 0property double _dY_draged: 0property double _dX_AngleDraged: 0property double _dY_AngleDraged: 0onPressed: {_rX_prev = mouseX;_rY_prev = mouseY;}onPositionChanged: {let dDraged360 = 360 * 8000 / 720;_dX_draged += mouseX - _rX_prev;if (_dX_draged > dDraged360) { _dX_draged = 0; }if (_dX_draged < -dDraged360) { _dX_draged = 0; }_dY_draged += mouseY - _rY_prev;if (_dY_draged > dDraged360) { _dY_draged = 0; }if (_dY_draged < -dDraged360) { _dY_draged = 0; }_dX_AngleDraged = _dX_draged * 720 / 8000;_dY_AngleDraged = _dY_draged * 720 / 8000;}onWheel: (wheel) => {if (wheel.angleDelta.y > 0){root._dScale++;if (root._dScale > 20) { root._dScale = 20; }}if (wheel.angleDelta.y < 0){root._dScale--;if (root._dScale < -20) { root._dScale = -20; }}}}

我认为代码应该见名知意了。我把MouseArea放在RobotArea里面,算是封装,外界调用时更简洁。逻辑上划分清楚。

数据类型:real和double通用就得了,没影响。

drag值:大于360或小于-360时让它归零,就实现无限翻转了。

滚轮wheel值:往前滚动是120,往后是-120,这个qt设计的不好,计数还得自己搞。这个数对应外界camera的z轴值,我的项目具体情况是,z轴取值正负20,同样要自己试过才知道多大值合适。

main_simple.qml:

最外层的界面。将来集成到项目时,也是参考此界面的代码,可以把RobotArea当做组件用。

    RowLayout {anchors.fill: parentColumnLayout {Layout.fillHeight: true//复位按钮Button {text: "Reset Posture"onClicked: {sldr_horizontal.value = 0;sldr_vertical.value = 0;_robot.f_ResetPosture();_robot._dScale = 0;}}//横向姿态RowLayout {Label { text: "horizontal" }Slider {id:sldr_horizontalfrom: -360to: 360value: 0}}Label { text: sldr_horizontal.value }//纵向姿态RowLayout {Label { text: "vertical" }Slider {id:sldr_verticalfrom: -360to: 360value: 0}}Label { text: sldr_vertical.value }...//远近、大小RowLayout {Label { text: "camera z" }Slider {id:sldr_cmr_zfrom: -20to: 20value: 0}}Label { text: sldr_cmr_z.value }...}RobotArea {id: _robotLayout.fillHeight: trueLayout.fillWidth: true//横纵姿态_dAngleHorizontal: sldr_horizontal.value_dAngleVertical: sldr_vertical.value//远近大小_dCameraZ: sldr_cmr_z.value...//拖拽、滚轮on_DX_AngleDragedChanged: sldr_horizontal.value = _dX_AngleDragedon_DY_AngleDragedChanged: sldr_vertical.value = _dY_AngleDragedon_DScaleChanged: sldr_cmr_z.value = -_dScale}}

以上种种,有些貌似能用属性绑定很简洁,但不行,有些会发生循环绑定。如果用过TabBar和SwipeView组合,一定知道官方代码有

        onCurrentIndexChanged: tabBar.setCurrentIndex(currentIndex)

setCurrentIndex函数就是设置当前索引,但不触发indexChanged信号,很显然就是有些绑定不能让它陷入死循环,要手动控制。这就是这类函数的意义。

效果:

完成上述这些,就可以愉快玩耍了。

左右拖拽:机器人左右转。

上下拖拽:机器人前后翻跟头。

滚轮上下:远缩小,近放大。

任意时候任意角度,可以随便看细节了。

如果不爽,点一下姿态重置按钮,一切从头开始。

本文完。

http://www.jsqmd.com/news/6444/

相关文章:

  • 2025 年挤压造粒机源头厂家最新推荐榜单:前五企业技术实力、服务能力及口碑测评指南对辊挤压/化肥挤压/干粉挤压造粒机厂家推荐
  • 网络与系统攻防技术实验一——逆向破解与Bof
  • “计算机配置\Windows 设置\安全设置\本地策略\审核策略” 配置后不生效
  • 2025 预分散颜料厂家最新推荐榜:超高含量技术 + 合规企业全景指南,纺丝 / 吹膜专用产品选型手册
  • 倍增思想与其优化
  • 2025 年 AI 健康管理领域推荐深护智康,社区、基层公卫、母婴 AI 健康管理、AI + 大健康管理、AI 健康管理师公司推荐
  • 2025 最新权威推荐:全国开锁公司口碑排行榜,含智能锁专项服务与紧急上门品牌详解汽车保险柜开锁/汽车锁开锁/保险柜开锁/智能开锁/快速上门开锁公司推荐
  • 从“看得见”到“能决策”:Operation Intelligence 重构企业智能运维新范式
  • 2025 年透骨液膏药代理加盟 / 足浴包膏药代理加盟 / 青岛膏药代理加盟推荐:青岛步泽药业布泽草本透骨液代理合作解析
  • QMT委托对象orderInfo的属性以及对应的值
  • 2025 年电动门厂家最新推荐排行榜:实力厂家深度解析,含技术认证、案例及选购指南
  • 单链表实现队列
  • 从手机到汽车音响:蚀刻喇叭网的跨界应用前景 - 指南
  • 读人形机器人27太空中
  • 2025 年酒店一次性用品源头厂家最新推荐榜单:含牙签牙线筷子套杯盖等全品类及采购选择指南酒店一次性牙签/牙线/筷子套/杯盖/杯垫/杯套用品 厂家推荐
  • Vue2 和 Vue3 中 watch 用法和原理详解 - 实践
  • 05-FreeRTOS的内存管理
  • 2025攻丝机品牌最新权威推荐排行榜:聚焦全自动攻丝机,半自动等机型,精选攻丝机实力厂商助企业高效选购
  • ​​AI重构混沌工程:智能韧性守护架构高可用时代已来​
  • 064_尚硅谷_短路与和短路或
  • oppoR9m刷Linux系统: 说明-注意事项-知识点
  • 手机框架材质
  • 2025年陶瓷定制企业最新推荐榜单:涵盖电子陶瓷,氧化铝陶瓷,氧化锆陶瓷,氮化铝陶瓷,结构陶瓷领域!
  • 2025阳台装修品牌推荐榜:优质阳台厂商资质、技术、服务测评及高口碑企业优选指南,浙江多为建筑服务与性价比兼具!
  • 2025 年杭州小程序开发机构最新推荐榜单:覆盖多行业定制需求,助力企业精准选靠谱服务商
  • 2025年杭州软件开发公司最新品牌推荐榜:聚焦技术实力与售后体系的优质服务商精选指南!
  • 湖南省茶陵一中校庆120周年:205班捐款
  • 实用指南:计算机网络-ipv4首部校验原理
  • 2025 年人工智能培训厂家最新推荐排行榜:聚焦人工智能培训合规运营机构、产业适配能力与教学实力深度解析
  • 一种以125kHz低频识别 + 2.4GHz数据传输”的方案,通过频率优势互补,为近距离物联网应用提供了可靠、精准且高效的解决方案